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())()"]
")(" -> [""]
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-题解的更多相关文章
- Leetcode之深度优先搜索(DFS)专题-301. 删除无效的括号(Remove Invalid Parentheses)
Leetcode之深度优先搜索(DFS)专题-301. 删除无效的括号(Remove Invalid Parentheses) 删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果. 说明 ...
- 301. Remove Invalid Parentheses
题目: Remove the minimum number of invalid parentheses in order to make the input string valid. Return ...
- LeetCode 301. Remove Invalid Parentheses
原题链接在这里:https://leetcode.com/problems/remove-invalid-parentheses/ 题目: Remove the minimum number of i ...
- [LeetCode] Remove Invalid Parentheses 移除非法括号
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...
- Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...
- Remove Invalid Parentheses 解答
Question Remove the minimum number of invalid parentheses in order to make the input string valid. R ...
- [Swift]LeetCode301. 删除无效的括号 | Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...
- [leetcode]301. Remove Invalid Parentheses 去除无效括号
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...
- LeetCode301. Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all ...
- 301. Remove Invalid Parentheses去除不符合匹配规则的括号
[抄题]: Remove the minimum number of invalid parentheses in order to make the input string valid. Retu ...
随机推荐
- 【算法学习】manacher
manacher太水了. 这篇blog不能称作算法学习,因为根本没有介绍…… 就贴个模板,太简单了…… #include<cstdio> #include<cstring> # ...
- 戴尔游匣5577安装 ubuntu/mint
这里以mint为例. 做好usb启动盘后, 启动到读秒的时候按上下方向键唤出如下选项: 在第二个选项里按 tab 键(上图界面有提示) 进去后有如下界面: 在后面加上参数: nouveau.modes ...
- Linux下C程序的反汇编【转】
转自:http://blog.csdn.net/u011192270/article/details/50224267 前言:本文主要介绍几种反汇编的方法. gcc gcc的完整编译过程大致为:预处理 ...
- C/C++杂记:NULL与0的区别、nullptr的来历
某些时候,我们需要将指针赋值为空指针,以防止野指针. 有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. 也有人直接使用0值作为空指针常量,例如:int* p = 0;. ...
- 关于一些问题的解决办法[记录]TF400017
这个问题是今天在改东西的时候,突然断电导致的,google了很久之后,终于找到了办法 方法: 就是删除下面这个文件 -========================================= ...
- 第一个Django项目:HelloWorld
OS:Windows家庭中文版, Python:3.6.3,Django:2.0.3 在前一篇文章中,Django已经顺利安装到了Python中,下面,开发第一个Python项目吧! 1.django ...
- day1作业:编写登陆接口
作业一:编写登陆接口 1.输入用户名和密码 2.认证成功后显示欢迎信息 3.输错三次后锁定 思路:要求是编写登陆接口,那么要有一个存放用户信息的模块:三次后锁定,要有一个存放锁定用户信息的模块:我们知 ...
- python之web框架(1):完成静态页面web服务器
python的web框架(1) 1.首先写一个最简单的web服务器,只能给客户回应一个固定的hello world的页面. from socket import * from multiprocess ...
- Ionic 自动创建应用的图标与启动画面
你只需要一个目录和两张图片就可以搞定.图片可以是 .png 的,Photoshop的 .psd,或者Illustrator的 .ai,(例如)命名为icon.png和splash.png.把这些图片放 ...
- Xiaoguang Tu's Home Page
Xiaoguang Tu (涂晓光): CV: Ph.D. Candidate of School of Communication and Information Engineering, Univ ...