思路:
也是要生成所有可能的组合,一看到这种就想全排列问题
第一思路是定义一个栈,因为每一次,需要加入的分支就两个,左括号或右括号。关键是每次栈也要回溯到之前的状态。
定义栈的思路也是对的,当走到底的时候,判断栈是否为空,为空则说明这个路径是有效的。
但是时间太长,效率很低,每次还需要多进行很多无效分支。
class Solution {
List<String> res = new ArrayList<String>();
public void getall(int n, int pop, StringBuffer route, LinkedList<Character> stack)
{
if(route.length()==n*2)
{
if(stack.isEmpty())
res.add(route.toString());
return;
}
//'('入栈
stack.push('(');
route.append('(');
getall(n,pop,route,stack);
stack.pop();//stack退回
route.deleteCharAt(route.length()-1);//route 退回
//')'入栈'
char c = ')';
if(!stack.isEmpty()) c= stack.peek();
if(c=='(')
{
route.append(')');
stack.pop();
getall(n,pop,route,stack);
stack.push(c);//stack 退回
route.deleteCharAt(route.length()-1);//route 退回
}
else
{
route.append(')');
stack.push(')');
getall(n,pop,route,stack);
stack.pop();//stack 退回
route.deleteCharAt(route.length()-1);//route 退回
}
}
public List<String> generateParenthesis(int n) {
getall(n,0,new StringBuffer(),new LinkedList<Character>());
return res;
}
思路2:
和栈的思路不一样的地方在于,每一次都进行判断,判断需要加入的是左括号还是右括号,当走到底的时候,一定就是有效的路径。
判断条件是个难点:
记录当前路径中的左括号数量和右括号数量,open , close.
每次遍历,都判断当前路径中的左括号数量是否小于n。小于n则加入左括号。继续递归。再恢复。
然后判断当前路径中的右括号数量是否小于左括号,小于则加入右括号。继续递归。再恢复。
递归退出条件是当前的路径长度==2*n
class Solution {
List<String> res = new ArrayList<>();
public List<String> generateParenthesis(int n) {
getall(n,0,0,new StringBuffer());
return res;
}
public void getall(int n, int open, int close, StringBuffer route)
{
if(route.length()==n*2)
{
res.add(route.toString());
return;
}
if(open<n)
{
open++;
route.append('(');
getall(n,open,close,route);
open--;
route.deleteCharAt(route.length()-1);
}
if(close<open)
{
close++;
route.append(')');
getall(n,open,close,route);
close--;
route.deleteCharAt(route.length()-1);
}
}
}