刷了一个困难题,一如既往做不出来,然后看题解,然后再自己打一遍…记录这个题的原因是,这其实是一类题目!!!先看看题目再分析。
题目描述:
删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。
说明: 输入可能包含了除 ( 和 ) 以外的字符。
示例 1:
输入: “()())()”
输出: ["()()()", “(())()”]
示例 2:
输入: “(a)())()”
输出: ["(a)()()", “(a())()”]
示例 3:
输入: “)(”
输出: [""]
分析题目:
这真的是一类题,题目具有的特征:
1.求的是一个子集
2.且子集满足一定的条件
这类题目可以用一个方法,就是DFS
关于这题DFS的分析:
1.DFS遍历的行为?删括号
2.什么情况下删?就是当左括号或者右括号有多的时候,正好当前遍历的又是个多的括号,就删!!!之后再继续进行DFS遍历删除
3.出口是什么?当没有多余的括号的时候!!!但注意此时还需要检查一下当前的字符串是否合法(即左右括号是否匹配!)
解题步骤:
1. 先统计多余的括号,注意并不是循环一遍统计左右括号个数,然后多的一方就是多余的。
如 left= 2,right = 3,就认为右括号多一个,因为可能之前的不匹配!!!
正确的统计方法是,当遇到左括号left++,遇到右括号时,若left > 0 就left --,说明一对括号匹配消除,若left == 0 ,right++,那么这样留下来的就是多余的括号,没有被匹配的括号!!!
2. 然后开始DFS,从第一个字符串开始,若当前符号是多余需要删除,则删除,
如:此时DFS遍历时left = 0,right = 1,当前是s[ i ] 为左括号则跳过,若为右括号则删除,
然后对后面进行递归DFS。
3. 直到left 为 0 ,right为 0,进行检查,匹配加入set< string >
代码如下:
class Solution {
public:
bool checks(string s){
int left = 0;
for(int i = 0;i < s.size();i++){
if(s[i] == '(') left++;
else if(s[i] == ')'){
if(!left) return false;
else left--;
}
}
return true;
}
void dfs(set<string> &result,string s,int left,int right,int index){
if(!left&&!right){
if(checks(s)) result.insert(s);
return ;
}
for(int i = index;i < s.size();i++){
if(s[i] == '('&&left) dfs(result,s.substr(0,i)+s.substr(i+1,s.size()-i-1),left-1,right,i);
else if(s[i] == ')'&&right) dfs(result,s.substr(0,i)+s.substr(i+1,s.size()-i-1),left,right-1,i);
}
}
vector<string> removeInvalidParentheses(string s) {
int left = 0;
int right = 0;
for(int i = 0;i < s.size();i++){
if(s[i] == '(') left++;
else if(s[i] == ')'){
if(left > 0) left--;
else right++;
}
}
set<string> result;
dfs(result,s,left,right,0);
return vector<string>(result.begin(),result.end());
}
};
总结:
关于DFS不要怕,步骤就是,首先递归的操作,其次递归的出口!!!

本文探讨了一类求解子集并满足特定条件的问题,通过深度优先搜索(DFS)解决去除无效括号的挑战。文章详细分析了如何统计多余括号、执行DFS遍历及检查字符串合法性,提供了完整代码实现。

被折叠的 条评论
为什么被折叠?



