301. Remove Invalid Parentheses

问题描述:

Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

Note: The input string may contain letters other than the parentheses ( and ).

Example 1:

Input: "()())()"
Output: ["()()()", "(())()"]

Example 2:

Input: "(a)())()"
Output: ["(a)()()", "(a())()"]

Example 3:

Input: ")("
Output: [""]

 

解题思路:

这道题要求我们返回所有最小删除后有效的括号字符串。

可以考虑用BFS来解答这道题。

对string的每一个 '('  ')' 我们都删除一下试试看看能不能构成一个合法的括号匹配。

对于非 '('  ')' 我们选择跳过。

由于我们只需要找最少操作的字符串。所以我们可以记录一个长度:

    当遇到的字符串的长度与给出字符串长度的差大于这个长度时,说明我们已经记录完所有最少操作的长度啦。

需要注意的几个点:

  1. 操作后的字符串可能会重复,为了避免重复,用set来存储并且检查

  2.检查字符串是否合法时,跳出循环后需检查计数器是否大于0,若大于0则说明有多余的左括号。

  3.原字符串可能就是一个有效的匹配

 

学习一下跑的比较快的解法。递归解法。

大佬的思路是找到出现重复的')'对之前的字符串中为')'的进行删除,若有连续的为了保证不重复,则只删除第一个。

再对字符串的后面部分进行检查。

当查完后,再对是否有重复的'(' 进行检查。

虽然我觉得还是有点晕但这个运行效率确实666

 

还有Grandyang总结的所有解法

 

代码:

BFS的解答:

class Solution {
public:
    vector<string> removeInvalidParentheses(string s) {
        vector<string> ret;
        if(isValid(s)){
            ret.push_back(s);
            return ret;
        } 
        unordered_set<string> st;
        queue<string> q;
        q.push(s);
        int movement = INT_MAX;
        int sLen = s.size();
        
        while(!q.empty()){
            string cur = q.front();
            q.pop();
            int n = cur.size();
            if(n + movement == sLen)
                break;
            for(int i = 0; i < n; i++){
                string temp = cur;
                if(temp[i] != '('&& temp[i] != ')')
                    continue;
                temp.erase(i, 1);
                if(isValid(temp)){
                    if(sLen - n + 1 < movement){
                        movement = sLen - n + 1;
                    }
                    if(!st.count(temp)){
                        ret.push_back(temp);
                    }
                }else{
                    if(!st.count(temp)){
                        q.push(temp);
                    }
                }
                st.insert(temp);
            }
        }
        return ret;
    }
private:
    bool isValid(string s){
        int cnt = 0;
        for(int i = 0; i < s.size(); i++){
            if(s[i] == '(') cnt++;
            else if(s[i] == ')'){
                cnt--;
                if(cnt < 0)
                    return false;
            }
        }
        if(cnt > 0)
            return false;
        return true;
    }
};

 

 

运行速度很快的解答:

class Solution {
private:
    char pa[2] = { '(' , ')' }; //检测右括号是否多余
    char pa_re[2] = { ')' , '(' }; //检测左括号是否多余
    void remove(string s, vector<string> &ans, int last_i, int last_j, const char pa[]) {
        for (int i = last_i, count = 0; i < s.size(); ++i) {
            if (s[i] == pa[0]) ++count;
            if (s[i] == pa[1]) --count;
            //直到我们找到有且仅有产生一个括号多余的情况
            if (count >= 0) continue;
            //前面的任意一个括号都可以去掉,如果有多个连续,则默认去掉第一个
            for (int j = last_j; j <= i; ++j)
                if (s[j] == pa[1] && (j == last_j || s[j - 1] != pa[1])) {
                    string newStr = s.substr(0, j) + s.substr(j + 1);
                    remove(newStr, ans, i, j, pa);
                }
            return;
        }

        //倒转字符串
        string reversed_str = s;
        std::reverse(reversed_str.begin(), reversed_str.end());

        //确认我们是否已经检测过左括号,如果已经检测过,则可以放入答案中,如果还没有检测则检测左括号
        if (pa[0] == '(') {
            //说明还没检测过
            remove(reversed_str, ans, 0, 0, pa_re);
        }
        else
            //已经检测过
            ans.push_back(reversed_str);
    }
public:
    vector<string> removeInvalidParentheses(string s) {
        vector<string> ans;
        remove(s, ans, 0, 0, pa);
        return ans;
    }
};

 

posted @ 2018-06-17 06:38  妖域大都督  阅读(173)  评论(0编辑  收藏  举报