题目链接: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; };