1249. Minimum Remove to Make Valid Parentheses**
https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/
题目描述
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 withB
), whereA
andB
are valid strings, or - It can be written as (
A
), where A is a valid string.
Example 1:
Input: s = "lee(t(c)o)de)"
Output: "lee(t(c)o)de"
Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted.
Example 2:
Input: s = "a)b(c)d"
Output: "ab(c)d"
Example 3:
Input: s = "))(("
Output: ""
Explanation: An empty string is also valid.
Example 4:
Input: s = "(a(b(c)d)"
Output: "a(b(c)d)"
Constraints:
1 <= s.length <= 10^5
s[i]
is one of'('
,')'
and lowercase English letters.
C++ 实现 1
使用两个栈分别存储 (
以及 )
的索引. 使用哈希表 record
统计要删除的符号的索引. 使用栈的好处是, 对于 (
可以找到最近的匹配的 )
.
class Solution {
public:
string minRemoveToMakeValid(string s) {
stack<int> left, right;
for (int i = 0; i < s.size(); ++ i) {
if (s[i] == '(') left.push(i);
else if (s[i] == ')') right.push(i);
}
unordered_set<int> record;
while (!left.empty() && !right.empty()) {
auto a = left.top(), b = right.top();
// 如果存在 ( 出现在 ) 后面的情况, 比如上面的
// example3 "))((", 那么删除 (
// 否则, 说明两者刚好配对, 同时弹出.
if (a > b) {
record.insert(a);
left.pop();
} else {
left.pop();
right.pop();
}
}
// 如果存在 ( 和 ) 不完全匹配的情况,
// 将索引加入 record
while (!left.empty()) {
record.insert(left.top());
left.pop();
}
while (!right.empty()) {
record.insert(right.top());
right.pop();
}
string res;
// 删除出现在 record 中的字符
for (int i = 0; i < s.size(); ++ i) {
if (!record.count(i)) res += s[i];
}
return res;
}
};
C++ 实现 2
来自 Java/C++ Stack. 该解法使用一个栈, 保存 (
的索引.
- 如果找到匹配的
)
, 那么将(
弹出 - 如果
)
多余, 将其替换为*
, 用*
表示该符号最后要删除 - 如果最后发现
(
多余, 将这些(
替换为*
最后灵活应用库函数 std::remove
删除 *
(移到 s
的末尾).
class Solution {
public:
string minRemoveToMakeValid(string s) {
stack<int> st;
for (auto i = 0; i < s.size(); ++i) {
if (s[i] == '(') st.push(i);
if (s[i] == ')') {
if (!st.empty()) st.pop();
else s[i] = '*';
}
}
while (!st.empty()) {
s[st.top()] = '*';
st.pop();
}
s.erase(remove(s.begin(), s.end(), '*'), s.end());
return s;
}
};
C++ 实现 3
来自 LeetCode 的 Submission. 和 C++ 实现 2
思路一致, 只不过要删除的符号用 ' '
来替代. 另一方面, 不采用 stack 保存 (
, 而是用 sum
统计 (
的个数.
class Solution {
public:
string minRemoveToMakeValid(string &s) {
const int n = s.size();
int sum = 0;
for (int i = 0; i < n; ++i) {
if (s[i] == '(') ++sum;
else if (s[i] == ')') {
if (sum) --sum;
else s[i] = ' ';
}
}
for (int i = n - 1; i >= 0 && sum; --i)
if (s[i] == '(') --sum, s[i] = ' ';
string ans;
for (char c : s) if (c != ' ') ans += c;
return ans;
}
};