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 ...
随机推荐
- Android Framebuffer介绍及使用【转】
转自:https://www.jianshu.com/p/df1213e5a0ed 来自: Android技术特工队 作者: Aaron 主页: http://www.wxtlife.com/ 原文连 ...
- TreeCollection2
Tree Collection 2 Table of Contents Introduction Structure Interfaces Data Node structure Tree struc ...
- FastDFS集群部署
之前介绍过关于FastDFS单机部署,详见博文:FastDFS+Nginx(单点部署)事例 下面来玩下FastDFS集群部署,实现高可用(HA) 服务器规划: 跟踪服务器1[主机](Tracker S ...
- poj1063
题意:有一些珠子排成一圈,珠子有两种颜色:黑和白.每次操作可以调换中间隔着一个珠子的两珠子的位置,给出这个圈子的初始状态,问最终能否通过操作让圈子中所有同色的珠子排在一起,即黑白分开. 分析:分两种情 ...
- table中的td等长(不随内容大小变化)
使用的table时候发现td的长度是随着内容的大小而变化的,但是有的时候我们不希望这样.想要td等长可以在 tbale中加上 style=“table-layout:fixed” ...
- 20155309 《Java程序设计》实验三(Java面向对象程序设计)实验报告
一.实验内容及步骤 (一)编码标准 在IDEA中使用工具(Code->Reformate Code)把代码重新格式化. (二)在码云上把自己的学习搭档加入自己的项目中,确认搭档的项目加入自己后, ...
- 动态页面技术JSP/EL/JSTL
本节内容: jsp脚本和注释 jsp运行原理 jsp指令(3个) jsp内置/隐式对象(9个) jsp标签(动作) EL技术 JSTL技术 JavaEE的开发模式 动态页面技术:就是在html中嵌入j ...
- hdu 4664 划线(SG)
N个平面,每个平面有ni个点 两个人玩游戏,划线,他们可以划任意一个平面的两个点,有以下要求:两个人划得线不能交叉,不要划已经划过的线,如果一个平面被划了一个空心的三角形,那么这个平面就不能继续划线了 ...
- jquery插件使用记录
1.imgPreview(图片预览功能插件) demo地址:http://james.padolsey.com/demos/imgPreview/full/
- 【BZOJ】4894: 天赋
题解 这道题是求一个有向图的外向生成树 入度矩阵对应着外向生成树,出度矩阵对应着内向生成树,知道了这个就可以求出基尔霍夫矩阵了,同时n - 1阶主子式一定要删掉根节点的一行一列 代码 #include ...