leetcode 301. Remove Invalid Parentheses

题目大意

给定一个字符串,可能会包括’(‘,’)’,和其他字符,得到所有合理的记过,实际上也就是左右括号匹配问题。
例子:
“()())()” -> [“()()()”, “(())()”]
“(a)())()” -> [“(a)()()”, “(a())()”]
“)(” -> [“”]

解题思路

参考:https://discuss.leetcode.com/topic/34875/easy-short-concise-and-fast-java-dfs-3-ms-solution

We all know how to check a string of parentheses is valid using a stack. Or even simpler use a counter.
The counter will increase when it is ‘(‘ and decrease when it is ‘)’. Whenever the counter is negative, we have more ‘)’ than ‘(‘ in the prefix.

意思是检查一个字符串的左右括号是否合理匹配的最简单的方法就是从左到右遍历字符串,一直要维持这个prefix的左括号的数目不大于右括号的数目。一旦右括号数目大于左括号的数目就没有必要继续往下看了,必须把多出来的右括号删掉。
不需要用stack,只要用一个计数器,这个计数器记录遍历至当前字符时,’(‘与’)’的数量差,合理字符串是不可能出现counter<0的情况的,一旦遇到counter<0就说明需要删掉某个’)’使得字符串重新获得合理状态。

那么,删掉那个右括号呢?
用个例子解释:
leetcode 301. Remove Invalid Parentheses_第1张图片
删除’)’的时候,如果有一串连续的’)’,只需要删除这串’)’中的任意一个都能得到一样的合理字符串,为了避免得到重复的结果,约定只删除第一个’)’。
删除的时候用DFS的思想,首先删掉第一个多出来的右括号,再递归处理。

经过上述处理,已经将左括号数目>右括号数目的case fix了,但是其实counter>0也是代表字符串是不合理的,如‘(()(()’,需要删掉’(‘,最简单的方法就是从右到左再run一遍,很妙的想法是求原字符串的逆序,如”((()”会变成”)))(“原字符串在本算法里面是合理的,但是逆字符串却不是合理的,这样直接递归就能处理这种情况了,只不过逆序之后实际的左括号是’)’,右括号是’(‘。

#include 
#include 
#include 
using namespace std;
class Solution {
public:
    vector<string> removeInvalidParentheses(string s) {
        vector<string> res;
        recursiveRomove(res, s, 0, 0, '(', ')');
        return res;
    }
private:
    void recursiveRomove(vector<string> &resultVec, string s, int startInd, int deleteInd, char leftBracket, char rightBracket) {
        int counter = 0;
        for (int i = startInd; i < s.length(); i++) {
            if (s[i] == leftBracket) {
                counter++;
            } else if (s[i] == rightBracket) {
                counter--;
            }
            if (counter >= 0) {
                continue;
            }
            for (int j = deleteInd; j <= i; j++) {
                if (s[j] == rightBracket && (j == deleteInd || s[j - 1] != rightBracket)) {
                    recursiveRomove(resultVec, s.substr(0, j) + s.substr(j + 1, s.length() - j - 1), i, j, leftBracket, rightBracket);
                }
            }
            return; //只有符合条件的字符串才可能逆序检查
        }
        string reverseStr(s.rbegin(),s.rend());
        if (leftBracket == '(') {
            recursiveRomove(resultVec, reverseStr, 0, 0, ')', '(');
        } else {
            resultVec.push_back(reverseStr);
        }
    }
};
int main(int argc, const char * argv[]) {
    Solution s;
    //")(f" s[j - 1] != rightBracket "((()" j == deleteInd
    string str = "((()";
    vector<string> r = s.removeInvalidParentheses(str);
    for (int i = 0; i < r.size(); i++) {
        cout << r[i] << endl;
    }
    return 0;
}

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