301. 删除无效的括号
给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。
示例 1:
输入:s = “()())()”
输出:[“(())()”,“()()()”]
示例 2:
输入:s = “(a)())()”
输出:[“(a())()”,“(a)()()”]
示例 3:
输入:s = “)(”
输出:[“”]
提示:
1 <= s.length <= 25
s 由小写英文字母以及括号 ‘(’ 和 ‘)’ 组成
s 中至多含 20 个括号
解题
方法一:回溯
题意让我们删除括号使得剩下的括号匹配,要求我们删除最少的括号数,并且要求得到所有的结果。我们可以使用回溯算法,尝试遍历所有可能的去掉非法括号的方案。
可以先统计出左括号的数量和右括号的数量,然后利用括号匹配的规则,计算出要最少删除的左括号和右括号的数量,然后我们尝试在原字符串 s 中去掉该数量的左括号和右括号,然后检测剩余的字符串是否合法匹配,如果合法匹配则我们则认为该字符串为可能的结果。
// 时间 O(n * 2^n) , 其中 n 为字符串的长度。考虑到一个字符串最多可能有 2^n个子序列,每个子序列可能需要进行一次合法性检测
// 空间O(n^2), 递归 调用栈的深度
class Solution {
// 存放结果
List<String> ans = new ArrayList<>();
public List<String> removeInvalidParentheses(String s) {
// 记录要删除的左括号、右括号的数量
int lremove = 0;
int rremove = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
lremove++;
} else if (s.charAt(i) == ')') {
if (lremove == 0) {
// 右括号数量多了
rremove++;
} else {
lremove--;
}
}
}
// 深度优先搜索 字符串(开始回溯)
handle(s, 0, lremove, rremove);
return ans