为何用BFS而不是DFS
利用BFS理解起来要远远比DFS要简单的多,因为这道题说的是删除最少的括号!!,如果我们每次只删除一个括号,然后观察被删除一个括号后是否合法,如果已经合法了,我们就不用继续删除了啊。因此我们并不需要将遍历进行到底,而是层层深入,一旦达到需求,就不再深入了。
如何进行BFS
在进行BFS之前,要先判断 ’ ( '和 ’ ) '是否有需要删除的,然后在根据需要删除的 ’ ( '和 ’ ) '的数量,他们对应的需要删除的数量对应的就是需要进行搜索的层数。
(即假如需要删除的 '(‘的数量是2,那么第一次先列举出删除一个’('后的所有可能的情况(不管删除以后是否合法),然后在在这基础上重复之前的操作再列举再删除一个’('后的所有情况)
以题目的例子为例
通过判断知道需要删除的只有一个 ‘)’(因为’(‘有3个,而’)‘有4个,显然’)‘多了一个)
那么就列举出在删除一个’ ) '后的所有可能的情况
第一层:[ ( ( ) ) ( ) , ( ) ( ) ( ) , ( ) ( ) ( ) , ( ) ( ) ) ( ]
由于只需删除一个,所有列举一次就行,然后只需对该层的所有结果进行合法性判断
注(由于可能在列举过程中会出现重复的现象,因此可以使用set来进行每一层数据的存储,避免重复)
代码如下
class Solution {
public List<String> removeInvalidParentheses(String s) {
//统计需要删除的'('和')'的数量
int left=0;
int right=0;
for (int i=0;i<s.length();i++){
if (s.charAt(i)=='('){
left ++;
}else if (s.charAt(i)==')'){
if (left>0){
left--;
}else {
right++;
}
}
}
ArrayList<String> arry = new ArrayList<String>();
HashSet<String> set = new HashSet<String>();
ArrayList<String> output = new ArrayList<String>();
arry.add(s);
//删除'('
while (left>0){
ArrayList<String> temp = new ArrayList<String>();
for (int i=0;i<arry.size();i++){
String str = arry.get(i);
for (int j=0;j<str.length();j++){
if (str.charAt(j)=='('){
String remove = str.substring(0,j)+str.substring(j+1);
if (!set.contains(remove)){
set.add(remove);
temp.add(remove);
}
}
}
}
arry = temp;
left--;
}
//删除')'
while (right>0){
ArrayList<String> temp = new ArrayList<String>();
for (int i=0;i<arry.size();i++){
String str = arry.get(i);
for (int j=0;j<str.length();j++){
if (str.charAt(j)==')'){
String remove = str.substring(0,j)+str.substring(j+1);
if (!set.contains(remove)){
set.add(remove);
temp.add(remove);
}
}
}
}
arry = temp;
right--;
}
//将删除后的所有字符串进行合法性判断,如果合法则加入list集合中
for (String word:arry){
if (judge(word)){
output.add(word);
}
}
return output;
}
private boolean judge(String word) {
Stack<Character> stack = new Stack<Character>();
for (int i=0;i<word.length();i++){
char c = word.charAt(i);
if (c=='('){
stack.add(c);
}else if (c==')'){
if (stack.size()>0){
stack.pop();
}else {
return false;
}
}
}
return true;
}
}
总结:用该方法很明了地体现了广度优先搜索的分层(层层递进)进行搜索的特点