题意

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())()"]

")(" -> [""]

Credits:

Special thanks to @hpplayer for adding this problem and creating all test cases.

Subscribe to see which companies asked this question

思路

无论是BFS还是DFS,其都是去判断字符串去掉括号的情况,如果不满足情况,则继续去除括号

题解

DFS

/**
* DFS+剪枝
*
* @param pair 多出来的遇见括号的个数
* @param index 记录字符串s的当前位置
* @param remove_left 左括号需要删除的个数
* @param remove_right 右括号需要删除的个数
* @param s 原始字符串
* @param solution 生成字符串
* @param result 存储所有的字符串结果
*/
void helper(int pair, int index, int remove_left, int remove_right, const string& s, string solution, unordered_set<string> &result) {
if (index == s.size()) {
if (pair == 0 && remove_left == 0 && remove_right == 0)
result.insert(solution);
return ;
} if (s[index] == '(') {
// 删除左边括号
if (remove_left > 0) helper(pair, index + 1, remove_left - 1, remove_right, s, solution, result);
// 回溯
helper(pair + 1, index + 1, remove_left, remove_right, s, solution + s[index], result);
}
else if (s[index] == ')') {
// 删除右边括号
if (remove_right > 0) helper(pair, index + 1, remove_left, remove_right - 1, s, solution, result);
// 回溯
if (pair > 0) helper(pair - 1, index + 1, remove_left, remove_right, s, solution + s[index], result);
}
else {
helper(pair, index + 1, remove_left, remove_right, s, solution + s[index], result);
}
}
vector<string> removeInvalidParentheses(string s) {
int remove_left = 0, remove_right = 0;
unordered_set<string> result; // 处理重复 // 计算左右两边需要删除括号的个数
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(')
remove_left++;
else if (s[i] == ')') {
if (remove_left > 0) remove_left--;
else remove_right++;
}
} helper(0, 0, remove_left, remove_right, s, "", result); return vector<string>(result.begin(), result.end());
}

BFS

  • 解法1
bool check(string s) {
int count = 0;
for (int i = 0; i < s.size(); i++) {
char tmp = s[i];
if (tmp == '(') count++;
if (tmp == ')') {
if (count == 0) return false;
count--;
}
}
return count == 0;
} /**
* 这个解法看似和上面解法类似,以为是DFS,但是其实是个BFS,思路和2是类似的,只不过用递归实现
* 删除子串的每个字符,然后进行递归
*
*
* @param begin 记录原字符串的下标,为什么是BFS的原因
* @param remove_left 需要删除左边括号的个数
* @param remove_right 需要删除右边括号的个数
* @param s 子串
* @param result 结果
*/
void helper2(int begin, int remove_left, int remove_right, string s, vector<string> &result) {
// 如果左右已经没有要删除的括号,并且符合条件,则进行收敛
if (remove_left == 0 && remove_right == 0) {
if (check(s)) {
result.push_back(s);
return;
}
} // begin是个重点,意味着从begin开始往后删,前面的字符串不再动
for (int i = begin; i < s.size(); ++i) {
string temp = s;
if (remove_left > 0 && remove_right == 0 && s[i] == '(') {
// 删除子串的每个字符,同时避免重复
if (begin == i || s[i] != s[i-1]) {
temp.erase(i, 1);
helper2(i, remove_left-1, remove_right, temp, result);
}
}
if (remove_right > 0 && s[i] == ')') {
if (begin == i || s[i] != s[i-1]) {
temp.erase(i, 1);
helper2(i, remove_left, remove_right-1, temp, result);
}
}
} }
vector<string> removeInvalidParentheses3(string s) {
int remove_left = 0, remove_right = 0;
vector<string> result; // 处理重复 // 计算左右两边需要删除括号的个数
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(')
remove_left++;
else if (s[i] == ')') {
if (remove_left > 0) remove_left--;
else remove_right++;
}
} helper2(0, remove_left, remove_right, s, result); return result;
}
  • 解法2
/**
* 通过从输入字符串中移除每一个括号,生成新的字符串加入到队列中
* 如果从队列中取出的字符串是有效的,则加入到结果列表中
* 一旦发现有效的字符串,则不再向队列中补充新的字符串,其去掉的括号数一定是最小的
* 而此时,队列中存在的元素与队列头元素去掉的括号数的差值 <= 1
* 并且,只有与队列头元素去掉括号数目相同的元素才有可能是候选答案
*
* @param s <#s description#>
*
* @return <#return value description#>
*/
vector<string> removeInvalidParentheses2(string s) {
vector<string> result;
if (s == "") {
result.push_back(s);
return result;
} unordered_set<string> visited; // 控制是否访问过字符串,因为要求不可重复
deque<string> queue;
queue.push_back(s);
visited.insert(s); bool found = false;
while (!queue.empty()) {
string temp = queue.front();
queue.pop_front(); // 每次遍历代表着需要加进来去掉一个括号的子串,层数代表删除括号的次数
// 只要第一次符合情况了,说明该字符串已经是可去掉括号数目最小的字符串层
// 意味着该层不再需要加进来任何的子串了,
if (check(temp)) {
result.push_back(temp);
found = true;
} if (found) continue;
for (int i = 0; i < temp.size(); ++i) {
if (temp[i] != '(' && temp[i] != ')') continue;
// 删除括号,生成新的字符串
string str = temp.substr(0, i) + temp.substr(i+1); if (visited.find(str) == visited.end()) {
queue.push_back(str);
visited.insert(str);
}
}
} return result;
}

Remove-Invalid-Parentheses-题解的更多相关文章

  1. Leetcode之深度优先搜索(DFS)专题-301. 删除无效的括号(Remove Invalid Parentheses)

    Leetcode之深度优先搜索(DFS)专题-301. 删除无效的括号(Remove Invalid Parentheses) 删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果. 说明 ...

  2. 301. Remove Invalid Parentheses

    题目: Remove the minimum number of invalid parentheses in order to make the input string valid. Return ...

  3. LeetCode 301. Remove Invalid Parentheses

    原题链接在这里:https://leetcode.com/problems/remove-invalid-parentheses/ 题目: Remove the minimum number of i ...

  4. [LeetCode] Remove Invalid Parentheses 移除非法括号

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...

  5. Remove Invalid Parentheses

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...

  6. Remove Invalid Parentheses 解答

    Question Remove the minimum number of invalid parentheses in order to make the input string valid. R ...

  7. [Swift]LeetCode301. 删除无效的括号 | Remove Invalid Parentheses

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...

  8. [leetcode]301. Remove Invalid Parentheses 去除无效括号

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...

  9. LeetCode301. Remove Invalid Parentheses

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...

  10. 301. Remove Invalid Parentheses去除不符合匹配规则的括号

    [抄题]: Remove the minimum number of invalid parentheses in order to make the input string valid. Retu ...

随机推荐

  1. Pool thread stack traces: Thread[C3P0PooledConnectionPoolManager[identityToken->原因解决办法

    今天本地连接测试库测试,发现早上还是好的,下午就崩了,报这个错,使用的是c3po连接池: , 纠结了好久,发现是数据库连接用光了,很多人都在连,果断换了本地库,好使了,看百度说把macPoolSizz ...

  2. ip分片重组 ip_defrag

    在ip_local_deliver中,如果检测到是分片包,则需要进行分片重组: ip_local_deliver |-->ip_is_fragment //判断是否为分片包 |-->ip_ ...

  3. 一步一步搭建11gR2 rac+dg之DG 机器配置(七)【转】

    DG 机器配置 转自: 一步一步搭建11gR2 rac+dg之DG 机器配置(七)-lhrbest-ITPUB博客http://blog.itpub.net/26736162/viewspace-12 ...

  4. python网络编程-同步IO和异步IO,阻塞IO和非阻塞IO

    同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network IO. ...

  5. No.5 selenium学习之路之多窗口句柄

    多窗口相关操作 获取当前句柄 c_handle = driver.current_window_handle 获取所有句柄 all_handle = driver.window_handles 切换到 ...

  6. 洛谷P2661信息传递

    传送门啦 一个人要想知道自己的生日,就意味着信息的传递是成环的,因为每轮信息只能传递一个人,传递的轮数就等于环的大小 环的大小就等于环中的两个点到第三个点的距离之和加一,我们就可以在使用并查集时,维护 ...

  7. opencv(0)安装与配置

    1.windows下 1.1 exe安装 windows下可以安装opencv的exe版本,已经编译好了,很省事. 到https://opencv.org/releases.html下载需要的open ...

  8. Cocos2d-x for Windows Phone 用法总结

    鉴于诺基亚(微软移动这个没人用的手机)开发者比较少,cocos2dx移植方面更是少的问题,总结一下WP8移植方面的资料,希望对大家有用,自己也当作笔记留念. 1.WP8方面有两种方式创建项目,Hell ...

  9. activeMQ 持久化配置

    Mac 中安装activeMQ brew install activemq 启动 activemq start 控制台:在浏览器中输入url: http://localhost:8161/ A:持久化 ...

  10. 使用require.js编写模块化JS

    layout: post title: 使用requirejs编写模块化代码 category: javascript date: 2016-10-22 00:00:00 tags: javascri ...