DI String Match
EasyPrompt
A permutation perm of n + 1 integers of all the integers in the range [0, n] can be represented as a string s of length n where:
s[i] == 'I'ifperm[i] < perm[i + 1], ands[i] == 'D'ifperm[i] > perm[i + 1].
Given a string s, reconstruct the permutation perm and return it. If there are multiple valid permutations perm, return any of them.
Example 1:
Input: s = "IDID"
Output: [0,4,1,3,2]Example 2:
Input: s = "III"
Output: [0,1,2,3]Example 3:
Input: s = "DDI"
Output: [3,2,0,1]
Constraints:
1 <= s.length <= 105s[i]is either'I'or'D'.
Approaches
3 approaches with complexity analysis and trade-offs.
This approach builds the permutation step-by-step, from left to right. At each position, it tries to place an unused number that satisfies the current 'I' or 'D' constraint. If it hits a dead end, it backtracks and tries a different number.
Algorithm
- Initialize an empty permutation
permof sizen+1and a boolean arrayusedof sizen+1to track used numbers. - Define a recursive function
backtrack(k, perm, used). - Base Case: If
k == n + 1, a valid permutation has been found. Returntrue. - Recursive Step: Iterate
numfrom0ton.- If
used[num]isfalse:- If
k > 0, check the constraint withs[k-1]:- If
s[k-1] == 'I'andperm[k-1] >= num, this choice is invalid. Continue to the nextnum. - If
s[k-1] == 'D'andperm[k-1] <= num, this choice is invalid. Continue to the nextnum.
- If
- Place the number:
perm[k] = num,used[num] = true. - Make a recursive call:
if (backtrack(k + 1, perm, used)) return true;. - Backtrack:
used[num] = false.
- If
- If
- If the loop finishes without finding a solution, return
false. - Start the process by calling
backtrack(0, perm, used).
Walkthrough
We define a recursive function, say solve(index, current_perm, used_numbers). The function tries to fill current_perm[index]. The base case for the recursion is when index reaches n+1, which means we have successfully constructed a full permutation. In the recursive step, we iterate through all numbers from 0 to n. For each number num, if it has not been used yet, we check if placing it at current_perm[index] is valid by checking against current_perm[index-1] and s[index-1]. If it's valid, we place the number, mark it as used, and make a recursive call for solve(index + 1, ...). If the recursive call fails, we backtrack by undoing the choice and trying the next available number.
class Solution { public int[] diStringMatch(String s) { int n = s.length(); int[] perm = new int[n + 1]; boolean[] used = new boolean[n + 1]; backtrack(0, perm, used, s); return perm; } private boolean backtrack(int k, int[] perm, boolean[] used, String s) { int n = s.length(); if (k == n + 1) { return true; // Found a valid permutation } for (int num = 0; num <= n; num++) { if (!used[num]) { if (k > 0) { if (s.charAt(k - 1) == 'I' && perm[k - 1] >= num) { continue; } if (s.charAt(k - 1) == 'D' && perm[k - 1] <= num) { continue; } } perm[k] = num; used[num] = true; if (backtrack(k + 1, perm, used, s)) { return true; } used[num] = false; // Backtrack } } return false; }}Complexity
Time
O((n+1)!) in the worst case. Although pruning reduces the search space compared to brute-force, the complexity remains exponential.
Space
O(n) for the recursion stack depth and the `used` array.
Trade-offs
Pros
More efficient than brute-force as it prunes invalid branches of the search tree early.
It's a general strategy for solving constraint satisfaction problems.
Cons
Still too slow for the problem's constraints as the time complexity is fundamentally factorial/exponential.
Can lead to stack overflow for large
ndue to deep recursion.
Solutions
Solution
class Solution {public int[] diStringMatch(String s) { int n = s.length(); int low = 0, high = n; int[] ans = new int[n + 1]; for (int i = 0; i < n; i++) { if (s.charAt(i) == 'I') { ans[i] = low++; } else { ans[i] = high--; } } ans[n] = low; return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.