思路:先求出所有可能的排列组合,然后再判断每个是否是vaild parenthses。判断是否valid的方法很简单,创建一个counter,遍历string,每碰到开括号,counter++,碰到闭括号,counter–。在整个遍历过程中,counter必须一直保持>= 0,并且遍历结束后counter必须等于0。满足以上两个条件的话就是valid的,否则就不是valid。我的思路虽然是和答案一样的,但是很可惜我并没有成功实现找出所有的排列组合。看了标答后,发现答案是使用recursion实现的找出所有排列组合的,这个我看了下我是不可能想到的,哈哈哈,还得继续修炼。说实话因为这种没做出来真的挺可惜的,算法都想好了,不会实现,不是吧阿sir,这都行。话不多说了,直接上标准答案代码吧:
class Solution {
public List<String> generateParenthesis(int n) {
List<String> combinations = new ArrayList();
generateAll(new char[2 * n], 0, combinations);
return combinations;
}
public void generateAll(char[] current, int pos, List<String> result) {
if (pos == current.length) {
if (valid(current))
result.add(new String(current));
} else {
current[pos] = '(';
generateAll(current, pos+1, result);
current[pos] = ')';
generateAll(current, pos+1, result);
}
}
public boolean valid(char[] current) {
int balance = 0;
for (char c: current) {
if (c == '(') balance++;
else balance--;
if (balance < 0) return false;
}
return (balance == 0);
}
}
下面介绍第二种方法,我觉得确实很厉害,也是基于recursion实现的,但是他这个算法就真的很巧妙,下次回顾的时候,我希望自己不要嫌麻烦,跟着代码走一遍循环,去感受一下人家算法的巧妙之处,或者说去感受一下人家找规律的能力有多强!下面直接给代码,重要地方我都注释了:
class Solution {
public List<String> generateParenthesis(int n) {
if(n==0) return new ArrayList<String>(Arrays.asList("")); //这是初始化arraylist的一种方法
if(n==1) return new ArrayList<String>(Arrays.asList("()")); //asList(),convert array to list
Set<String> set=new HashSet<String>();
for(String str:generateParenthesis(n-1)){ //建议自己跟着循环自己走一遍就能明白这个算法了,这个recursion真的很巧妙
for(int i=0;i<str.length();i++){
set.add(str.substring(0,i+1)+"()"+str.substring(i+1,str.length()));
}
}
List<String> list = new ArrayList<String>(set); //这边用到的是arraylist的第三种构造函数来初始化的:ArrayList(Collection c)
return list;
}
}
还有第三种方法就是DFS,和学长交流后我发现基本要求all possible solutions的题都可以用dfs来做。dfs需要多多练习呀。下面给出dfs代码
public class Solution {
public void DFS(int l, int r, int n, String str, List<String> ans) {
if (l == n && r == n) {
ans.add(str);
}
if (l > r) {
DFS(l, r + 1, n, str + ")", ans);
}
if (l <= n) {
DFS(l + 1, r, n, str + "(", ans);
}
}
public List<String> generateParenthesis(int n) {
List<String> ans = new ArrayList<>();
DFS(0, 0, n, "", ans);
return ans;
}
}
总结:
- 要熟悉stringbuilder构造函数,有好几种;要熟悉arraylist构造函数,也有好几种。
- 要熟悉dfs的定义,深度遍历,要搭配着二叉树去学习dfs。