zoukankan      html  css  js  c++  java
  • 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;
        }
    };
  • 相关阅读:
    gil
    异步
    字符串 最长回文字串
    字符串 最长公共前缀
    数组 合并区间
    python 排序
    2021.9.3 阿里笔试AK贴
    SIP协议详解
    fiddler抓包各字段的含义
    常见的HTTP状态码列表
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/9191962.html
Copyright © 2011-2022 走看看