Problem
Solution
题意为,给定一个字符串,让你移除最少的不合法的括号,让剩下的字符串合法,所给的字符串中可能含有(、)之外的字符。返回所有合法的字符串。
这题个人感觉比较难,ac前参考了很多别人的博客。
做这题时,我们需要明确以下几个事情:
1、如何判断一个括号字符串是否合法?一个长度为n的字符串下标为0~n-1,那么对于任何一个0 ~n-2上的字符,都需要保证左括号的数量>=右括号的数量,否则就是不合法的;在n-1上,如果左括号数量=右括号数量,那么这个串最终就是合法的,否则就是不合法的。
2、如何判断最少的不合法括号?方法是,从左到右遍历字符串,记录整个字符串里不合法的左括号数量、不合法的右括号数量。(这条为什么成立我也还没弄明白)
3、由第2条得到的左右括号不合法数量去删除,先删不合法的右括号,再删不合法的左括号,可以达到搜索剪枝的目的。
搞清了以上,那么就可以用深搜来搜索所有的可能性,把移除数为最少且剩下的合法字符串加入最终结果中。
class Solution {
public:
vector<string> removeInvalidParentheses(string s) {
int n=s.size();
if(!n) return {""};
int l=0,r=0;
for(auto ch:s){
if(ch=='(') ++l;
else if(ch==')'){
if(l==0) ++r;
else --l;
}
}
vector<string> ans;
dfs(s,0,l,r,ans);
return ans;
}
private:
bool check(string s){
int cnt=0;
for(auto ch:s){
if(ch=='(') ++cnt;
else if(ch==')') --cnt;
if(cnt<0) return false;
}
return cnt==0;
}
void dfs(string &s,int pos,int l,int r,vector<string> &ans){
if(l==0&&r==0&&check(s)) {
ans.push_back(s);
return;
}
for(int i=pos;i<s.size();++i){
if(i>pos&&s[i-1]==s[i]) continue;
if(s[i]==')'){
string curr=s;
curr.erase(i,1);
if(r>0) dfs(curr,i,l,r-1,ans);
}else if(s[i]=='('){
string curr=s;
curr.erase(i,1);
if(l>0) dfs(curr,i,l-1,r,ans);
}
}
}
};