DI String Match
EasyUpdated: Aug 2, 2025
Practice on:
Problem
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.
Examples
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 <= 10^5s[i]is either'I'or'D'.
Solution
Method 1 – Two Pointers (Greedy)
Intuition
We want to construct a permutation of [0, n] such that for each character in s:
- If s[i] == 'I', then perm[i] < perm[i+1]
- If s[i] == 'D', then perm[i] > perm[i+1]
The greedy way is to use two pointers: one starting at 0 (lo), one at n (hi). For each 'I', pick lo and increment; for each 'D', pick hi and decrement. This guarantees the required order.
Approach
- Initialize lo = 0 and hi = n (where n = len(s)).
- For each character in s:
- If 'I', append lo to ans and increment lo.
- If 'D', append hi to ans and decrement hi.
- After the loop, append the last remaining number (lo == hi).
- Return the constructed permutation.
Code
C++
class Solution {
public:
vector<int> diStringMatch(string s) {
int n = s.size(), lo = 0, hi = n;
vector<int> ans;
for (char c : s) {
if (c == 'I') ans.push_back(lo++);
else ans.push_back(hi--);
}
ans.push_back(lo);
return ans;
}
};
Go
func diStringMatch(s string) []int {
n := len(s)
lo, hi := 0, n
ans := make([]int, 0, n+1)
for _, c := range s {
if c == 'I' {
ans = append(ans, lo)
lo++
} else {
ans = append(ans, hi)
hi--
}
}
ans = append(ans, lo)
return ans
}
Java
class Solution {
public int[] diStringMatch(String s) {
int n = s.length(), lo = 0, hi = n;
int[] ans = new int[n+1];
for (int i = 0; i < n; ++i) {
ans[i] = s.charAt(i) == 'I' ? lo++ : hi--;
}
ans[n] = lo;
return ans;
}
}
Kotlin
class Solution {
fun diStringMatch(s: String): IntArray {
val n = s.length
var lo = 0
var hi = n
val ans = IntArray(n+1)
for (i in s.indices) {
ans[i] = if (s[i] == 'I') lo++ else hi--
}
ans[n] = lo
return ans
}
}
Python
class Solution:
def diStringMatch(self, s: str) -> list[int]:
n = len(s)
lo, hi = 0, n
ans = []
for c in s:
if c == 'I':
ans.append(lo)
lo += 1
else:
ans.append(hi)
hi -= 1
ans.append(lo)
return ans
Rust
impl Solution {
pub fn di_string_match(s: String) -> Vec<i32> {
let n = s.len();
let (mut lo, mut hi) = (0, n as i32);
let mut ans = Vec::with_capacity(n+1);
for c in s.chars() {
if c == 'I' {
ans.push(lo);
lo += 1;
} else {
ans.push(hi);
hi -= 1;
}
}
ans.push(lo);
ans
}
}
TypeScript
class Solution {
diStringMatch(s: string): number[] {
const n = s.length;
let lo = 0, hi = n;
const ans: number[] = [];
for (const c of s) {
if (c === 'I') ans.push(lo++);
else ans.push(hi--);
}
ans.push(lo);
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n), where n is the length of s. We process each character once. - 🧺 Space complexity:
O(n), for the output array.