Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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:
- Create a list A containing numbers from 0 to N (where N is length of S)
- 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)
- 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.
---