← Home

942. DI String Match

LeetCode article · C++ solution
Website made by wuisabel-gif · Original C++ code by keineahnung2345
greedyC++Markdown
942

This is one of those problems where the clean idea matters more than the amount of code. For 942. DI String Match, the solution in this repository is mainly a greedy solution.

Guide

What?

The first job is to translate the English prompt into state, transition, and stopping conditions. Instead of trying to be clever immediately, read the code as a sequence of questions:

  • What state are we keeping?
  • How do we move from one state to the next?
  • When do we know the answer is already determined?

For this file, the main tools are: greedy.

Guide

When?

This pattern shows up when the brute force version has too many repeated checks, too many possible branches, or too much bookkeeping to do by hand. The accepted code reduces that pressure by storing exactly the information that remains useful later.

The important function names to track are diStringMatch.

Guide

Why?

The point of the implementation is not to make the code longer. It is to avoid doing the same thinking twice.

  • The final return is not magic; it is the invariant after the loops or recursion have finished doing their accounting.

Guide

How?

Walk through the solution in this order:

  1. Start from the smallest reliable state.
  2. Expand one legal move at a time.
  3. Cache, count, or merge information as soon as it becomes settled.
  4. Let the final stored value answer the original question.

The most important competitive-programming habit here is to trust the invariant. Once the invariant is right, the loops become much less scary.

Guide

Complexity

  • Time: O(N), where N is the length of S.
  • Space: O(N).

Guide

C++ Solution

Your submission

The accepted solution

solution.cpp
01/**
02Given a string S that only contains "I" (increase) or "D" (decrease), let N = S.length.
03
04Return any permutation A of [0, 1, ..., N] such that for all i = 0, ..., N-1:
05
06If S[i] == "I", then A[i] < A[i+1]
07If S[i] == "D", then A[i] > A[i+1]
08 
09
10Example 1:
11
12Input: "IDID"
13Output: [0,4,1,3,2]
14Example 2:
15
16Input: "III"
17Output: [0,1,2,3]
18Example 3:
19
20Input: "DDI"
21Output: [3,2,0,1]
22 
23
24Note:
25
261 <= S.length <= 10000
27S only contains characters "I" or "D".
28**/
29
30/**
31Approach 1: Greedy
32Intuition
33
34If we see say S[0] == 'I', we can always put 0 as the first element; similarly, if we see S[0] == 'D', we can always put N as the first element.
35
36Say we have a match for the rest of the string S[1], S[2], ... using N distinct elements. Notice it doesn't matter what the elements are, only that they are distinct and totally ordered. Then, putting 0 or N at the first character will match, and the rest of the elements (1, 2, ..., N or 0, 1, ..., N-1) can use the matching we have.
37
38Algorithm
39
40Keep track of the smallest and largest element we haven't placed. If we see an 'I', place the small element; otherwise place the large element.
41
42Complexity Analysis
43
44Time Complexity: O(N), where N is the length of S.
45
46Space Complexity: O(N). 
47
48**/
49//Your runtime beats 55.92 % of cpp submissions.
50class Solution {
51public:
52    vector<int> diStringMatch(string S) {
53        vector<int> ans;
54        
55        int low = 0;
56        int high = S.size();
57        
58        for(int i = 0; i < S.size(); i++){
59            if(S[i]=='I')
60                ans.push_back(low++);
61            else
62                ans.push_back(high--);
63        }
64        // ans.push_back(high); 
65        ans.push_back(low);
66        return ans;
67    }
68};

Cost

Complexity

Time
O(N), where N is the length of S.
Dominated by the main traversal, recursion, or data-structure operations in the code.
Space
O(N).
Auxiliary state plus the answer structure where the problem requires one.