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; } };