Hard超高频
看了很久Discussion里面最高票的答案,一直没看懂。晚上开始看后面的答案,发现了一个BFS的方法比较好理解。其实这个方法的思路很brute force, 就是每次我们删掉一个括号(左或右),检查剩下的string是不是valid. 每次选择一个位置,就只需要遍历整个string用O(N)完成。一开始这个方法听起来会耗费很多时间,但因为我们一是会用一个set来记录访问过的string(也同时保证了答案没有duplicate),二是只要删着删着找到一个需要删掉括号符号的最小个数我们就不用继续了,因为这个问题本来就是让我们求出需要删掉最少个数invalid parentheses的解。
我们用一个boolean found来记录是不是找到了那个删除最少非法括弧后第一个出现的valid string. 如果说找到了,我们就加到答案里,并且found = true. 一开始我疑惑为什么循环末尾我们不把found reset成false呢。后来一想,这个BFS每一层的元素都是长度相同的string,也就是上一层选择某个位置的字符删掉后剩下的那些字符。所以当我们found = true后,我们其实就知道不用再继续找下面的层了,也就是不需要再往queue里offer东西。就只需要把当前queue里剩下的元素继续check isValid完就好。这也是为什么我们不能找到一个就break出来。因为如果这一层还有其他string isValid, 我们得全部加到res里面。
这个isValid method写得也比较直接,就是用一个count 来计算(
的个数,遇到)
就想当于匹配一个,所以count –. 这样如果我们遍历到)
时count <= 0那肯定invalid. 这样最后再check一下count == 0?就好了。
class Solution {
public List<String> removeInvalidParentheses(String s) {
List<String> res = new ArrayList<>();
if (s == null){
return res;
}
Set<String> visited = new HashSet<>();
Queue<String> queue = new LinkedList<>();
visited.add(s);
queue.offer(s);
boolean found = false;
while (!queue.isEmpty()){
String curt = queue.poll();
if (isValid(curt)){
res.add(curt);
found = true;
}
if (found){
continue;
}
for (int i = 0; i < curt.length(); i++){
if (curt.charAt(i) != '(' && curt.charAt(i) != ')'){
continue;
}
String next = curt.substring(0, i) + curt.substring(i+1);
if (!visited.contains(next)){
queue.offer(next);
visited.add(next);
}
}
}
return res;
}
private boolean isValid(String s){
int count = 0;
for (char c : s.toCharArray()){
if (c == '('){
count++;
} else if (c == ')'){
if (count == 0){
return false;
} else {
count--;
}
}
}
return count == 0;
}
}