Remove Invalid Parentheses 删除无效的括号

删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。

说明: 输入可能包含了除 ( 和 ) 以外的字符。

示例 1:

输入: "()())()"
输出: ["()()()", "(())()"]

示例 2:

输入: "(a)())()"
输出: ["(a)()()", "(a())()"]

示例 3:

输入: ")("
输出: [""]

这道题翻译了discuss的最高票解答(能看懂答案就不错了)

这道题的基本思想是找到多余的括号(注意是所有的),所以基本思路是采用回溯法找到所有有效解,然后加入答案中,先来看几点启发:

1:怎么找到多余的括号,在Valid Parentheses中,通过stack或者两个计数器left和right分别记录左括号和右括号的个数,可以验证一个左右括号是否符合要求。

2:如何限制在指定序列中的有效括号数,比如str=()()),采用计数方法(left和right计数器)来统计,发现left=2,right=3,由于left-right>=0,所以当前的子字符串多了一个右括号,需要删除一个),我们可以删除str[1],形成str=(()),也可以删除str[3],形成str=()(),为了避免重复出现答案,这里规定只删除第一个不符合要求的左括号,因为第二种情况会在后面的回溯中遍历到)。

我们规定几个变量的意思:start_to_count开始计数左右括号的位置,start_to_remove开始准备删除第一个不符合要求右括号的起始搜索点(start_to_remove<=start_to_count)

class Solution {
public:
    void Core(string s,vector & res,int start_to_count,int start_to_remove,vector &par){
        int count=0; //采用计数器来统计左右括号数
        for(int i=start_to_count;i=0) continue; 如果左括号个数>=右括号个数,继续寻找
            
            for(int j=start_to_remove;j<=i;j++){ //能进到for循环表示count小于0,表示一定要删除一个右括号,那么从start_to_remove开始寻找,找到第一个不满足要求的右括号的位置。
                if(s[j]==par[1] && (j==start_to_remove || s[j-1]!=par[1])){ //第一个多余的右括号的下标是s[j]==par[1],但是也要考虑边界条件:比如j是第一个元素这种情况
                    Core(s.substr(0,j)+s.substr(j+1),res,i,j,par); //那么删除第一个右括号后的有效字符串就是把第j个字符删掉的剩下的字符串,即new_str=s.substr(0,j)+s.substr(j+1),由于前面i个(下标)字符已经是有效的字符,且把第j个字符给删了,还要考虑新字符串new_str的长度少了1,那么新的开始搜索的字符下标new_start_to_count=i+1-1=i,同理new_start_to_remove=j+1-1,所以递归调用自身,对应参数设置如上所示。
                }
            }
            return;  //return这里已经处理了剩下子串的所有情况,直接返回,不然会有重复数据。
        }
        reverse(s.begin(),s.end()); //反转原字符,从右往左搜索删除多余的左字符
        if(par[0]=='('){
            vector tmp={')','('};
            Core(s,res,0,0,tmp);
        }
        else res.push_back(s);
    }
    vector removeInvalidParentheses(string s) {
        vector par={'(',')'};
        vector res;
        Core(s,res,0,0,par);
        return res;
    }
};

 

 

你可能感兴趣的:(算法)