Make The String Great
Easy · Stack · Explanation and code example
Two Pointers
How it works
Instead of using extra space for a stack, we can simulate it in-place using two pointers. The left pointer l represents the "top" of our virtual stack, while the right pointer r scans through the input. Characters before position l form our result. When we find a bad pair, we "pop" by decrementing l.
Steps
- Convert the string to a mutable array and initialize
l = 0. - For each position
rfrom0to the end:- If
l > 0and the character atrforms a bad pair with the character atl - 1(ASCII difference of32), decrementlto "pop" the pair. - Otherwise, copy the character at
rto positionland incrementl.
- If
- Return the substring from index
0tol.
Complexity
- Time complexity:
O(n) - Space complexity:
O(1)orO(n)depending on the language.
Things to watch for
Checking Only for Case Difference Without Same Letter
A "bad" pair requires two conditions: the characters must be the same letter AND have different cases. Checking only s[i] != s[i-1] is insufficient because characters like 'a' and 'B' are different but not a bad pair. You must also verify they are the same letter when case is ignored.
Off-by-One Errors in Index Management
When removing a bad pair and backtracking, the index must be decremented by 2 (not 1) to recheck the newly adjacent characters. Using i -= 1 instead of i -= 2 causes the algorithm to skip potential new bad pairs created by the removal.
Python code example
class Solution:
def makeGood(self, s: str) -> str:
l = 0
s = list(s)
for r in range(len(s)):
if l > 0 and abs(ord(s[r]) - ord(s[l - 1])) == 32:
l -= 1
else:
s[l] = s[r]
l += 1
return ''.join(s[:l])
C++ code example
class Solution {
public:
string makeGood(string s) {
int l = 0;
for (int r = 0; r < s.length(); r++) {
if (l > 0 && abs(s[r] - s[l - 1]) == 32) {
l--;
} else {
s[l++] = s[r];
}
}
return s.substr(0, l);
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.