(题目内容直接复制LeetCode)
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
刚开始看到这道题感觉不是很有头绪,不知道把所有的情况都给搞出来,而且不知道搞出来后又是怎么将这种所有的情况以那样的顺序输出出来(别喷,我是菜鸡我知道)。然后就去看了看题解,然后自己就闷着头去搞了。
然后自己写了出来,然后按照后面的题解又改进了下。
我的思路如下:
看着示例你会发现,有一个规律就是在不违背一个"(" 对应 ")"一个的前提下,它会尽可能的将”(“放在前面。也就是说。也就是说我们要做的就是跟他一样,在不违背规则的情况下,尽可能的将"("往前放。所以我们怎么才可以不违背规则呢,我们可以用left记录左括号的数量,用right记录右括号的数量,只要我们的每一步放置之后都保持left>=right就可以了,如果在某一步之后违背了这个规则,就说明这一步的选择是不合法的,那么我们就进行剪枝,不用继续向下进行。
题解中给了一个判断一个字符数组是否合法的方法,代码如下:
public boolean valid(char arr[]){
int sum=0;
int pos=0;
while(pos<arr.length){
if(arr[pos]=='('){
sum++;
}else{
sum--;
}
if(sum<0){
return false;
}
pos++;
}
if(sum>0){
return false;
}
return true;
}
我的代码如下:
class Solution{
int sum1=0;
int num;
ArrayList result=new ArrayList<String>();
char arr[];
Solution(int n){
this.num=n*2;
arr=new char[2*n];
}
/**
*
* @param pos 记录char数组填充的位置
* @param left 记录"("的数量
*/
public void solution(int pos,int left){
//所有的位置全部选完 直接进入判断
if(pos==num){
// 下面的输出是我查看中间数组的方法
// System.out.println("sum1="+(++sum1));
// for(int i=0;i<arr.length;i++){
// System.out.print(arr[i]);
// }
// System.out.println();
// 下列代码是我进行最后的判断,但是我发现在我过程中的每一次剪枝都会确保我们的数据一直都是符合格式的,也就是每一次
// 的选择之后数据都会保持"("的数量大于等于")"的数量。因此最后的判断也就是不必要的了。
// if(valid(arr)){
// result.add(new String(arr));
System.out.println("yes");
// }
result.add(new String(arr));
return;
}
//如果"("数量大于等于一半 那就不用再选择"("
if(left>=num/2){
arr[pos++]=')';
solution(pos,left);
pos--;
}
//如果已经填充的位置上的")"数量大于"("的数量 说明不合法,所以直接结束
else if(pos-left>left){
return ;
}
//这个时候无论选择哪一个都可以,且每个位置都有两种选择,
else{
arr[pos]='(';
solution(pos+1,left+1);
arr[pos]=')';
solution(pos+1,left);
}
}
}