class Solution:
def minRemoveToMakeValid(self, s: str) -> str:
s = list(s)
stack = []
for i, c in enumerate(s):
if c == '(':
stack.append(i)
elif c == ')':
if stack:
stack.pop()
else:
s[i] = ''
while stack:
s[stack.pop()] = ''
return ''.join(s)
class Solution {
public:
string minRemoveToMakeValid(string s) {
vector<int> stack;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(') stack.push_back(i);
else if (s[i] == ')') {
if (!stack.empty()) stack.pop_back();
else s[i] = '*';
}
}
while (!stack.empty()) {
s[stack.back()] = '*';
stack.pop_back();
}
string res;
for (char c : s) {
if (c != '*') res += c;
}
return res;
}
};
class Solution {
public String minRemoveToMakeValid(String s) {
StringBuilder sb = new StringBuilder(s);
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) == '(') {
stack.push(i);
} else if (sb.charAt(i) == ')') {
if (!stack.isEmpty()) {
stack.pop();
} else {
sb.setCharAt(i, '*');
}
}
}
while (!stack.isEmpty()) {
sb.setCharAt(stack.pop(), '*');
}
StringBuilder res = new StringBuilder();
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) != '*') {
res.append(sb.charAt(i));
}
}
return res.toString();
}
}
var minRemoveToMakeValid = function(s) {
let arr = s.split('');
let stack = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === '(') {
stack.push(i);
} else if (arr[i] === ')') {
if (stack.length) {
stack.pop();
} else {
arr[i] = '';
}
}
}
while (stack.length) {
arr[stack.pop()] = '';
}
return arr.join('');
};
Given a string s
containing lowercase letters and parentheses '('
and ')'
, your task is to remove the minimum number of parentheses so that the resulting string is a valid parentheses string. A string is considered valid if all opening parentheses have a corresponding closing parenthesis and all closing parentheses have a corresponding opening parenthesis, and the parentheses are properly nested.
s
can be up to 105.
For example, given s = "a)b(c)d"
, the output could be "ab(c)d"
.
The core challenge is to ensure that every opening parenthesis '('
has a matching closing parenthesis ')'
, and vice versa. If we encounter an unmatched parenthesis, we need to remove it.
A brute-force approach would try removing every possible parenthesis and checking if the string is valid, but this is extremely inefficient, especially for large strings.
Instead, we can use a stack to keep track of the positions of unmatched parentheses as we scan the string. When we find a closing parenthesis without a matching opening one, we mark it for removal. Similarly, after scanning, any unmatched opening parentheses left in the stack should also be removed.
This stack-based approach is efficient and avoids unnecessary work, making it suitable for large inputs.
s
into a mutable array (or StringBuilder in Java) to allow in-place modifications.'('
.'('
, push its index onto the stack.')'
:
'('
in the stack, pop from the stack (they match).')'
for removal (e.g., set it to an empty character or a placeholder).'('
; mark those for removal as well.We use a stack because it efficiently keeps track of unmatched opening parentheses, and marking characters for removal allows us to construct the final valid string in one pass.
Let's take s = "lee(t(c)o)de)"
as an example.
"lee(t(c)o)de"
The result is a valid string with the minimum number of removed parentheses.
s
. We iterate over the string at most twice (once for marking, once for building the result).The optimized solution is efficient and suitable for large input sizes.
To make a parentheses string valid with the minimal number of removals, we use a stack to efficiently track unmatched opening parentheses and mark unmatched closing parentheses for removal as we scan the string. This approach ensures a linear time solution, avoids unnecessary computation, and leverages the properties of stacks for matching pairs. The final result is built by skipping all invalid parentheses, yielding a valid string with minimal edits.