题目描述
给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。
示例 1:
输入:s = “()())()”
输出:["(())()","()()()"]
示例 2:
输入:s = “(a)())()”
输出:["(a())()","(a)()()"]
示例 3:
输入:s = “)(”
输出:[""]
提示:
1 <= s.length <= 25
s 由小写英文字母以及括号 ‘(’ 和 ‘)’ 组成
s 中至多含 20 个括号
解题思路
题目让我们删除括号使得剩下的括号匹配,要求我们删除最少的括号数,并且要求得到所有的结果。我们可以使用回溯算法,尝试遍历所有可能的去掉非法括号的方案。
首先我们利用括号匹配的规则求出该字符串s 中最少需要去掉的左括号的数目lremove 和右括号的数目rremove,然后我们尝试在原字符串 ss 中去掉 lremove 个左括号和rremove 个右括号,然后检测剩余的字符串是否合法匹配,如果合法匹配则我们则认为该字符串为可能的结果,我们利用回溯算法来尝试搜索所有可能的去除括号的方案。
在进行回溯时可以利用以下的剪枝技巧来增加搜索的效率:
充分利用括号左右匹配的特点(性质),因此我们设置变量 lcount 和 rcount,分别表示在遍历的过程中已经用到的左括号的个数和右括号的个数,当出现lcount<rcount 时,则我们认为当前的字符串已经非法,停止本次搜索。
我们从字符串中每去掉一个括号,则更新lremove 或者 rremove,当我们发现剩余未尝试的字符串的长度小于lremove+rremove 时,则停止本次搜索。
当lremove 和 rremove 同时为0 时,则我们检测当前的字符串是否合法匹配,如果合法匹配则我们将其记录下来。
由于记录的字符串可能存在重复,因此需要对重复的结果进行去重,去重的办法有如下两种:
利用哈希表对最终生成的字符串去重。
我们在每次进行搜索时,如果遇到连续相同的括号我们只需要搜索一次即可,比如当前遇到的字符串为(((())",去掉前四个左括号中的任意一个,生成的字符串是一样的,均为((())",因此我们在尝试搜索时,只需去掉一个左括号进行下一轮搜索,不需要将前四个左括号都尝试一遍。
思路是leetcode的官方思路,但是官方给的c++代码里有一点奇怪的判断,在代码中做了一些修改
代码
class Solution {
public:
vector<string> ans;
vector<string> removeInvalidParentheses(string s) {
//int i,n=s.size();
int lremove=0,rremove=0;
//首先我们利用括号匹配的规则求出该字符串s中最少需要去掉的左括号的数目lremove和右括号的数目rremove
for(char c:s){
if(c=='('){
lremove++;
}
else if(c==')'){
if(lremove>0) lremove--;
else rremove++;
}
}
strdelete(s,0,lremove,rremove);
return ans;
}
void strdelete(string str, int start,int lremove, int rremove){
if(lremove==0&&rremove==0){
if(isValid(str)){
ans.push_back(str);
}
return;
}
int i,n=str.size();
for(i=start;i<n;i++){
//这种情况在i-1时已经讨论过了
if(i>start&&str[i]==str[i-1]) continue;
//剩下的字符无法满足删除括号的数目
if(lremove+rremove>n-i) return;
//尝试去掉一个左括号
if(lremove>0&&str[i]=='('){
strdelete(str.substr(0,i)+str.substr(i+1),i,lremove-1,rremove);
}
//尝试去掉一个右括号
if(rremove>0&&str[i]==')'){
strdelete(str.substr(0,i)+str.substr(i+1),i,lremove,rremove-1);
}
}
}
inline bool isValid(const string &s){
int cnt=0;
for(char c:s){
if(c=='('){
cnt++;
}
else if(c==')'){
cnt--;
if(cnt<0) return false;
}
}
return cnt==0;
}
};