[leetcode] 301. Remove Invalid Parentheses 解题报告

题目链接:https://leetcode.com/problems/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 ).

Examples:

"()())()" -> ["()()()", "(())()"]
"(a)())()" -> ["(a)()()", "(a())()"]
")(" -> [""]


思路:本题有两种方法来做。

第一种DFS,其思想是去掉一个括号,然后计算其失配括号是否小于原来的字符串,如果不小于,则说明去掉这个括号并无法得到一个更好的解,则不再往下搜索此分支。

如果去掉一个括号之后得到的失配括号小于原字符串,则说明去掉这个括号是有效的,因此可以继续往下搜索。

举个栗子(()(()()

这个字符串的失配括号是2,因此去掉第一个括号之后得到的子串失配括号是1,因此子串是有效的,继续往下是有可以得到解的。

而如果去掉第三个括号,得到的子串失配括号将会是3,因此此子串不可能得到解。

在遍历的时候可能会碰到去掉一个括号得到和以前一样的字符串,这种情况需要跳过,不然会得到重复的解。

DFS的运行时间是128 ms

代码如下:

class Solution {
public:
    int cal(string str)//计算失配括号
    {
        int num = 0;
        stack<int> st;
        for(int i = 0; i< str.size(); i++)
        {
            if(str[i] == '(')
                st.push(i);
            else if(str[i] == ')')
            {
                if(st.empty())  
                    num++;
                else    
                    st.pop();
            }
        }
        num += st.size();
        return num;
    }
    void DFS(string str, int num)
    {
        if(num == 0)//如果已经完全匹配,则加入结果中
        {
            result.push_back(str);
            return;
        }
        for(int i = 0; i < str.size(); i++)
        {
            string substr = str.substr(0, i) + str.substr(i+1);
            if(mp.find(substr) != mp.end()) //如果已经访问过同样的字符串则跳过
                continue;
            else  
                mp[substr] = true;
            int newNum = cal(substr);
            if(newNum < num)//如果去掉当前的字符可以使失配括号减少,则继续    
                DFS(substr, newNum);
        }
    }

    vector<string> removeInvalidParentheses(string s) {
        DFS(s, cal(s));
        return result;
    }
private:
    map<string, bool> mp;
    vector<string> result;
};


第二种方法是BFS,这种方法的思想是如果一个字符串的括号不能完全匹配,则将其依次去掉一个括号的子串加入队列里。

如果找到了了第一个匹配的字符串,则比他短的字符串都不可能是解了,因此可以剪枝了。

运行时间是:588 ms

可见还是DFS快了几倍。

代码如下:

class Solution {
public:
    bool isValid(string s)//检查是否是合法的括号匹配
    {
        stack<int> st;
        for(int i = 0; i< s.size(); i++)
        {
            if(s[i] == '(')
                st.push(i);
            else if(s[i] == ')')
                if(st.empty())
                    return false;
                else
                    st.pop();
        }
        return st.empty();
    }
    void BFS(string s)
    {
        queue<string> que;
        que.push(s);
        while(!que.empty())
        {
            string str = que.front();
            que.pop();
            if(isValid(str))//当前字符串匹配
            {
                len = str.size();
                result.push_back(str);
                continue;
            }
            for(int i = 0; i< str.size(); i++)
            {
                if(str[i] != '(' && str[i] != ')')//跳过其他无关紧要的字符
                    continue;
                string substr = str.substr(0,i) + str.substr(i+1);
                if(mp.find(substr) != mp.end()) 
                    continue;//如果已经存在此此字符,则不再搜索
                else 
                    mp[substr] = true;
                if((int)substr.size() >= len)//如果还没有找到第一个完全匹配的字符
                    que.push(substr);
            }
        }
    }
    vector<string> removeInvalidParentheses(string s) {
        len = INT_MIN;
        BFS(s);
        return result;
    }
private:
    int len;
    map<string, bool> mp;
    vector<string> result;
};


参考:http://bookshadow.com/weblog/2015/11/05/leetcode-remove-invalid-parentheses/










你可能感兴趣的:(LeetCode,算法,DFS,bfs)