题目地址:
https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/
给定一个含括号的字符串 s s s(除了括号还可能含英文字母)。要求删去最少数量的括号,使得该字符串里的括号是合法的。返回任意删除括号后合法的字符串。
只需了解合法括号串的充分必要条件即可。一个括号串合法当且仅当:
1、任意前缀中左括号数大于等于右括号数;
2、全局来看左括号右括号数相等。
我们设计算法如下:用两个变量
l
l
l和
r
r
r分别记录遇到的左右括号数量。遍历
s
s
s,遇到非括号字符直接跳过,遇到左右括号时相应的计数加
1
1
1;如果发现
l
<
r
l<r
l<r,说明需要删右括号,将当前右括号的位置换成别的字符,同时将
r
r
r减去
1
1
1;遍历完整个字符串之后,如果
l
>
r
l>r
l>r,说明有
l
−
r
l-r
l−r个左括号需要删除,此时我们选择删除最后出现的
l
−
r
l-r
l−r个左括号,这样仍然能保证整个括号是合法的。代码如下:
class Solution {
public:
string minRemoveToMakeValid(string s) {
int l = 0, r = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] != '(' && s[i] != ')') continue;
s[i] == '(' ? l++ : r++;
// 如果l < r,说明当前的右括号要删除,则标记其为空格
if (l < r) s[i] = ' ', r--;
}
// 算一下需要删除的左括号数量
int del = l - r;
string res;
// 我们从后向前遍历,这样方便删除最后出现的del个左括号
for (int i = s.size() - 1; i >= 0; i--)
if (s[i] != ' ') {
if (s[i] == '(' && del > 0)
del--;
else
res += s[i];
}
// 最后翻转一下
reverse(res.begin(), res.end());
return res;
}
};
时空复杂度 O ( l s ) O(l_s) O(ls)。