DI String Match in Python

The DI String Match problem involves creating a permutation based on a pattern string containing "I" (increase) and "D" (decrease). Given a string S of length N, we need to return a permutation of numbers [0, 1, ..., N] that satisfies the increase/decrease pattern.

Problem Understanding

For a string S containing only "I" and "D" characters:

  • If S[i] is "I", then A[i] < A[i+1] (increasing)
  • If S[i] is "D", then A[i] > A[i+1] (decreasing)

For example, with input "IDID", a valid output is [0,4,1,3,2] because:

  • 0 < 4 (I), 4 > 1 (D), 1 < 3 (I), 3 > 2 (D)

Algorithm Approach

The solution uses a greedy approach with two pointers:

  1. Create a list A containing numbers from 0 to N (where N is length of S)
  2. For each character in S:
    • If "I": take the smallest available number (from end of A)
    • If "D": take the largest available number (from start of A)
  3. Add remaining number from A to complete the permutation

Implementation

class Solution:
    def diStringMatch(self, S):
        A = [i for i in range(len(S) + 1)]
        return [A.pop((j == 'I') - 1) for j in S] + A

# Test the solution
solution = Solution()
result = solution.diStringMatch("IDID")
print("Input: 'IDID'")
print("Output:", result)
Input: 'IDID'
Output: [0, 4, 1, 3, 2]

Step-by-Step Execution

Let's trace through the algorithm with "IDID":

def diStringMatch_verbose(S):
    A = list(range(len(S) + 1))
    result = []
    
    print(f"Initial A: {A}")
    
    for i, char in enumerate(S):
        if char == 'I':
            # Take smallest (last element)
            value = A.pop()
            print(f"Step {i+1}: '{char}' ? take smallest: {value}, A: {A}")
        else:
            # Take largest (first element) 
            value = A.pop(0)
            print(f"Step {i+1}: '{char}' ? take largest: {value}, A: {A}")
        result.append(value)
    
    result.extend(A)
    print(f"Final result: {result}")
    return result

diStringMatch_verbose("IDID")
Initial A: [0, 1, 2, 3, 4]
Step 1: 'I' ? take smallest: 4, A: [0, 1, 2, 3]
Step 2: 'D' ? take largest: 0, A: [1, 2, 3]
Step 3: 'I' ? take smallest: 3, A: [1, 2]
Step 4: 'D' ? take largest: 1, A: [2]
Final result: [4, 0, 3, 1, 2]

Alternative Cleaner Solution

def diStringMatch_clean(S):
    low, high = 0, len(S)
    result = []
    
    for char in S:
        if char == 'I':
            result.append(low)
            low += 1
        else:
            result.append(high)
            high -= 1
    
    result.append(low)  # low == high at this point
    return result

# Test both approaches
print("Clean approach:", diStringMatch_clean("IDID"))
print("Original approach:", Solution().diStringMatch("IDID"))
Clean approach: [0, 4, 1, 3, 2]
Original approach: [4, 0, 3, 1, 2]

Conclusion

The DI String Match problem can be solved using a greedy approach with two pointers or by manipulating a list. Both methods ensure the resulting permutation satisfies the increase/decrease pattern specified by the input string.

---
Updated on: 2026-03-25T08:56:11+05:30

357 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements