class Solution:
def isValid(self, s: str) -> bool:
stack = []
for ch in s:
stack.append(ch)
if len(stack) >= 3 and stack[-3:] == ['a', 'b', 'c']:
stack.pop()
stack.pop()
stack.pop()
return not stack
class Solution {
public:
bool isValid(string s) {
vector<char> stack;
for (char ch : s) {
stack.push_back(ch);
int n = stack.size();
if (n >= 3 && stack[n-3] == 'a' && stack[n-2] == 'b' && stack[n-1] == 'c') {
stack.pop_back();
stack.pop_back();
stack.pop_back();
}
}
return stack.empty();
}
};
class Solution {
public boolean isValid(String s) {
StringBuilder stack = new StringBuilder();
for (char ch : s.toCharArray()) {
stack.append(ch);
int n = stack.length();
if (n >= 3 && stack.charAt(n-3) == 'a' && stack.charAt(n-2) == 'b' && stack.charAt(n-1) == 'c') {
stack.delete(n-3, n);
}
}
return stack.length() == 0;
}
}
var isValid = function(s) {
let stack = [];
for (let ch of s) {
stack.push(ch);
let n = stack.length;
if (n >= 3 && stack[n-3] === 'a' && stack[n-2] === 'b' && stack[n-1] === 'c') {
stack.pop();
stack.pop();
stack.pop();
}
}
return stack.length === 0;
};
Given a string s
consisting only of the characters 'a'
, 'b'
, and 'c'
,
you are allowed to repeatedly perform the following operation as many times as possible:
"abc"
from s
.
Return true
if s
is empty after performing the above operation as many times as possible. Otherwise, return false
.
Constraints:
s.length
≤ 20,000.
The problem asks whether we can remove all characters from s
by repeatedly deleting "abc" substrings.
At first glance, one might consider brute-force approaches:
s
and removing it, then checking again until no "abc" remains.Instead, notice that every valid removal must be in the order "a" followed by "b" followed by "c", and removals can overlap. This suggests that we can process the string in a single pass, simulating the removals with a stack. Each time the top three elements of the stack form "abc", we remove them, as if we've found a valid substring to delete.
This stack-based approach efficiently models the process, ensuring we only remove valid "abc" substrings and handle overlaps naturally.
Let's describe the solution step by step:
s
:
true
. Otherwise, return false
.
Why use a stack? The stack helps us efficiently keep track of the last few characters and quickly identify when an "abc" can be removed, all in a single pass through the string. Stack operations (push and pop) are O(1), making this approach efficient.
Let's walk through an example with s = "aabcbc"
:
Stack is empty at the end, so we return true
.
s
. Each character is pushed and possibly popped at most once.
The key insight is that we can efficiently simulate the removal of "abc" substrings using a stack, processing the string in a single pass. This avoids the inefficiency of repeated searches and removals, and naturally handles overlaps. The stack approach is both simple and elegant, making it ideal for this type of sequential substring removal problem.