删除无效的括号
难度:
标签:
题目描述
给你一个由若干括号和字母组成的字符串 s
,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。
示例 1:
输入:s = "()())()" 输出:["(())()","()()()"]
示例 2:
输入:s = "(a)())()" 输出:["(a())()","(a)()()"]
示例 3:
输入:s = ")(" 输出:[""]
提示:
1 <= s.length <= 25
s
由小写英文字母以及括号'('
和')'
组成s
中至多含20
个括号
代码结果
运行时间: 58 ms, 内存: 16.0 MB
/*
* 题目思路:
* 通过使用Java Stream API来简化集合操作。
* 我们仍然使用BFS来查找最小数量的删除。
* 我们用流的方式处理队列和集合,避免显式地遍历集合。
*/
import java.util.*;
import java.util.stream.Collectors;
public class SolutionStream {
public List<String> removeInvalidParentheses(String s) {
if (s == null) return new ArrayList<>();
Set<String> visited = new HashSet<>();
Queue<String> queue = new LinkedList<>();
List<String> res = new ArrayList<>();
queue.add(s);
visited.add(s);
boolean found = false;
while (!queue.isEmpty()) {
int size = queue.size();
List<String> level = new ArrayList<>();
for (int i = 0; i < size; i++) {
String str = queue.poll();
if (isValid(str)) {
res.add(str);
found = true;
}
if (found) continue;
level.add(str);
}
if (found) continue;
level.forEach(str -> {
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != '(' && str.charAt(i) != ')') continue;
String newStr = str.substring(0, i) + str.substring(i + 1);
if (visited.add(newStr)) {
queue.add(newStr);
}
}
});
}
return res;
}
private boolean isValid(String s) {
int count = 0;
for (char c : s.toCharArray()) {
if (c == '(') count++;
if (c == ')') {
if (count == 0) return false;
count--;
}
}
return count == 0;
}
}
解释
方法:
这个题解采用深度优先搜索(DFS)的方法来解决删除无效括号的问题。首先,通过遍历字符串,统计需要删除的左括号和右括号的数量。然后,使用DFS递归地尝试删除字符串中的左括号或右括号,直到删除的数量满足要求。在递归过程中,如果当前字符串已经删除了所有需要删除的括号,就判断当前字符串是否有效,如果有效则加入结果集。为了避免重复结果,在递归时跳过连续相同的字符。
时间复杂度:
O(2^n)
空间复杂度:
O(n)
代码细节讲解
🦆
在DFS函数中,参数`open: int`的作用是什么,为什么需要这个参数?
▷🦆
如何保证在递归过程中避免产生重复的字符串?题解中提到了跳过连续相同的字符,请问这是如何实现的?
▷🦆
函数`isValid`是如何判断一个字符串是否有效?如果字符串含有字母,这种方法是否仍然适用?
▷🦆
在实现中,为何要在DFS函数里检查`l + r > len(s) - i`,这一条件具体是为了解决什么问题?
▷