以一个"()"为一个单位,往之前的左、中、右里面插,肯定是不行的。因为有重复的形式,需要剔除,很是麻烦。
正确思路是一个半括号一个半括号的添加。
添加的时候为了保证添加下去是符合括号规律的,必须满足,在现有基础上:
- 左括号的数量 < n
- 右括号的数量 <= 左括号的数量
这样,当右括号的数量 == n就表示没法继续添加了,说明此时是一个解。
public class Solution {
public List<String> generateParenthesis(int n) {
List<String> res = new ArrayList<String>();
if(n == 0) return res;
helper(res,n,0,0,new String());
return res;
}
public void helper(List<String> res, int n, int L, int R,String tempStr)
{
//System.out.println(tempStr + " " + L + " " + R);
if(R == n)
{
res.add(tempStr);
}
else
{
if(R < L)
{
helper(res,n,L,R+1,tempStr+")");
}
if(L < n)
{
helper(res,n,L+1,R,tempStr+"(");
}
}
}
}
上面的是二刷的结果。
一刷的时候做的很蠢,用的判断是,总数==现有半括号的2倍,然后再进行判断现有的括号是不是valid,比如N=4 ((((也会判断一下。
二刷的判断就聪明多了,不会生成错误的组合。可喜可贺。。至少在蠢逼的基础上进步了一点。。
-----
三刷。
右括号数量永远不大于左括号数量。
左括号数量永远不大于N。
根据这个2个来DFS剪枝。
重点
时间复杂度按理说是2^n,显而易见。。但是有说法是加上限制条件是n!,有可能……
Time: O(n!)
space: O(n)
public class Solution {
public List<String> generateParenthesis(int n) {
List<String> res = new ArrayList<>();
if (n == 0) return res;
dfs(res, n, new String(), 0, 0);
return res;
}
public void dfs(List<String> res, int n, String tempS, int l, int r) {
if (l + r == 2*n) {
if (l == r)
res.add(tempS);
return;
} else {
if (l + 1 <= n) {
String s1 = new String(tempS + "(");
dfs(res, n, s1, l + 1, r);
}
if (r + 1 <= l) {
String s2 = new String(tempS + ")");
dfs(res, n, s2, l, r + 1);
}
return;
}
}
}