题意

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. 【洛谷】【洛谷月赛】4月月赛Round 1/2

    洛谷月赛“月”来“月”丧了,一月更比一月丧,做得我十分不“月”…… 4月的两轮月赛,都只会T1,就写一下吧,等待后续更新…… 先看看Round1的T1: [R1T1] 网址:点我 [题意简述] 给定一 ...

  2. 搭建本地git服务器

    最近因为项目需求,需要实现一个原型系统,加上后期项目需要多人协作,考虑采用了git做版本控制. 这里主要简要描述下git服务器和客户端的搭建和配置. 1.git服务器 (1)安装git sudo ap ...

  3. linux快速复制大量小文件方法 nc+tar【转】

    1,在需要对大量小文件进行移动或复制时,用cp.mv都会显得很没有效率,可以用tar先压缩再解压缩的方式.  2,在网络环境中传输时,可以再结合nc命令,通过管道和tcp端口进行传输.  nc和tar ...

  4. oracle11g创建修改删除表

    oracle11g创建修改删除表 我的数据库名字: ORCL         密码:123456 1.模式 2.创建表 3.表约束 4.修改表 5.删除表 1.模式 set oracle_sid=OR ...

  5. Python之 context manager

    在context manager中,必须要介绍两个概念: with as... , 和 enter , exit. 下文将先介绍with语句,然后介绍 __enter__和exit, 最后介绍cont ...

  6. mysql -> 索引_07

    索引与sql语句优化 压力测试对比

  7. 七、springcloud之配置中心Config(二)之高可用集群

    方案一:传统作法(不推荐) 服务端负载均衡 将所有的Config Server都指向同一个Git仓库,这样所有的配置内容就通过统一的共享文件系统来维护,而客户端在指定Config Server位置时, ...

  8. docker stack 部署 mysql 5.6

    =============================================== 2018/7/1_第1次修改                       ccb_warlock === ...

  9. DevExpress GridControl 的数据绑定

    本人不才啊,折腾2个多小时才把数据绑定好.现在把折腾过程记录一下来以帮助更多的朋友,自己也温习一下. 直接上代码了哈.... WPF哈 xaml文件 <dxg:GridControl Name= ...

  10. 洛谷P2024食物链

    传送门啦 这道题的特殊之处在于对于任意一个并查集,只要告诉你某个节点的物种,你就可以知道所有节点对应的物种. 比如一条长为4的链 甲->乙->丙->丁 ,我们知道乙是A物种.那么甲一 ...