版权声明:转载请标明出处「OneDeveloper」 https://blog.csdn.net/OneDeveloper/article/details/84027659
得到全排列的组合,同时对于不符合要求的组合要剔除。
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
recall("", n, n,result);
return result;
}
/**
* @param leftCount 剩余可用的左括号个数
* @param rightCount 剩余可用的右括号个数
*/
public void recall(String s, int leftCount, int rightCount,List<String> result) {
// 没有括号可以进行组合了
if (leftCount == 0 && rightCount == 0) {
result.add(s);
} else {
if (leftCount>0) {
String tmp = s + '(';
int newLeftCount = leftCount - 1;
if (newLeftCount==rightCount) {
// 当左右括号已经使用了同样的个数,且目前为止组成的组合有效的话,
// 才继续递归,(剪枝,但是也增加了判断的时间成本)
// 因为有了这一步判断,则当 leftCount 和 rightCount 都为 0 时肯定
// 是符合条件的
if (isEffective(tmp)) recall(tmp, newLeftCount, rightCount,result);
} else {
recall(s + '(', newLeftCount, rightCount,result);
}
}
if (rightCount>0) {
String tmp = s + ')';
int newRightCount = rightCount - 1;
if (newRightCount==leftCount) {
if (isEffective(tmp)) recall(tmp, leftCount, newRightCount,result);
} else {
recall(tmp, leftCount, newRightCount,result);
}
}
}
}
// 判断组合是不是有效的
// 有效的定义就是对于 s[i] 如果是 '(',则在 s[j>i] 要存在 ')' 与之匹配
public boolean isEffective(String s) {
if (s!=null&&s.length()>0) {
Stack<Character> stack = new Stack<>();
char[] chars = s.toCharArray();
for (char c : chars) {
if (c=='(') stack.push('(');
else {
if (stack.isEmpty()) return false;
else stack.pop();
}
}
return true;
}
return false;
}
根据网站提交记录进一步的优化:
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
recall(n, n,"",result);
return result;
}
/**
* @param leftCount 剩余可用的左括号个数
* @param rightCount 剩余可用的右括号个数
*/
public void recall(int leftCount,int rightCount,String s,List<String> result) {
if (leftCount == 0 && rightCount == 0) {
result.add(s);
}
if (leftCount>0) recall(leftCount - 1, rightCount, s + '(', result);
if (rightCount>leftCount) recall(leftCount, rightCount - 1, s + ')', result);
}
可以发现,肯定是要先用 ‘(’
,然后才能用 ')'
与前面的 '('
匹配。