Given a string s of ‘(’ , ‘)’ and lowercase English characters.
Your task is to remove the minimum number of parentheses ( ‘(’ or ‘)’, in any positions ) so that the resulting parentheses string is valid and return any valid string.
Formally, a parentheses string is valid if and only if:
It is the empty string, contains only lowercase characters, or
It can be written as AB (A concatenated with B), where A and B are valid strings, or
It can be written as (A), where A is a valid string.
Example 1:
Input: s = “lee(t©o)de)”
Output: “lee(t©o)de”
Explanation: “lee(t(co)de)” , “lee(t©ode)” would also be accepted.
Example 2:
Input: s = “a)b©d”
Output: “ab©d”
Example 3:
Input: s = “))((”
Output: “”
Explanation: An empty string is also valid.
简单来说就是去除最少的无效括号。即左右括号要成对地匹配。
思路:
方法一:
括号配对一般会想到用stack。
这里stack保存的是左括号的位置,因为左括号多余的话,要把它们删掉,删掉要知道下标吧。
用一个StringBuilder保存 result string, 方便随时修改结果的字符串(input的字符串常量是不能修改的)。
遇到" ( “就在stack中存入下标,我们最后要修改的是result string,怎么判断” ( "在result string中的下标呢?
因为result string是一个一个压入字符保存的,当前长度就是下标。
遇到" ) “,就出栈,同时” ) “保存进result string(匹配的括号)。
如果stack为空,就说明没有与之匹配的” ( “,这时不保存” ) "进result string(等效为已经删掉了)
//33ms
public String minRemoveToMakeValid(String s) {
Stack<Integer> stack = new Stack<>();
StringBuilder result = new StringBuilder();
for(int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if(ch == '(') {
stack.push(result.length());
result.append(ch);
} else if(ch == ')') {
if(!stack.isEmpty()) {
stack.pop();
result.append(ch);
}
} else {
result.append(ch);
}
}
while(!stack.isEmpty()) {
result.deleteCharAt(stack.pop());
}
return result.toString();
}
方法二:
不用stack,仅用一个计数变量left, 来记" ( "有多少个。
先把string转为charArray, 因为input的string常量是不能修改的。
然后遍历一遍charArray,遇到" ( "就left ++计数。
遇到" ) “就left --,当left == 0时,说明没有与它匹配的左括号了,当前” ) “需要删除,
删除的操作是最后一起删,这时先把” ) “改为” * "。
上面的遍历可确保没有多余的" ) “了,但是可能还有多余的” ( “,这时left > 0,
从右到左遍历找出这些多余的” ( “, 也改为” * "。
最后直接在原charArray上修改,把" * "的地方跳过即可。
//8ms
public String minRemoveToMakeValid(String s) {
char[] chArr = s.toCharArray();
int left = 0;
//验证左括号的个数,标记多余的右括号为'*'
for(int i = 0; i < chArr.length; i ++) {
if(chArr[i] == '(') {
left ++;
} else if(chArr[i] == ')') {
if(left == 0) {
chArr[i] = '*';
} else {
left --;
}
}
}
//标记多余(left>0)的左括号为'*'
for(int i = chArr.length - 1; i >= 0; i--) {
if(left > 0 && chArr[i] == '(') {
left --;
chArr[i] = '*';
}
}
//把标记的'*'删掉
int id = 0;
for(int i = 0; i < chArr.length; i ++) {
if(chArr[i] != '*') {
chArr[id] = chArr[i];
id ++;
}
}
return new String(chArr).substring(0, id);
}