一、前言
给定 n,表示有 n 对括号, 请写一个函数以将其生成所有的括号组合,并返回组合结果。
输入: 3
输出: [“((()))”, “(()())”, “(())()”, “()(())”, “()()()”]
二、算法思路
我们可以将题目想象成给定2*n个格子,每个格子可以放入"(“或”)",因此我们可以利用递归不断地重复这个过程,穷举出所有的可能性。下边是深度优先的一般模板
/**
*@param level 递归当前层
*@param param 其它参数
*/
private void recursion(int level, ...Object param){
//退出递归的条件,当前递归层数大于临界值
if(level > MAX){
return;
}
//处理当前层的参数
processCurrentLevel(param);
//以不同的参数newParam1、newParam2,下探至下一层
recursion(int level+1, ...newParam1);
recursion(int level+1, ...newParam2);
//清理当前层的状态,例如全局变量等
clearStatus();
}
三、算法Java实现
方法一:暴力求解
public class Solution {
private List<String> result = new ArrayList<>();
/**
* @param n: n pairs
* @return: All combinations of well-formed parentheses
* we will sort your return value in output
*/
public List<String> generateParenthesis(int n) {
// write your code here
generate(1, 2*n, "");
return result;
}
private void generate(int level, int max, String s){
if(level > max){
/*此处可用栈进行括号匹配判断,即遇到左括号将右括号入栈,遇到右括号,
将其与栈顶元素比较,若相等则栈顶元素出栈,直到遍历完所有括号,栈不空则不是有效字符串*/
if(isValidBraket(s)){
result.add(s);
}
return;
}
//处理当前层状态
String s1 = s + "(";
String s2 = s + ")";
//以左括号下探
generate(level+1, max, s1);
//以右括号下探
generate(level+1, max, s2);
}
private boolean isValidBraket(String input){
Stack<Character> stack = new Stack();
for (int i = 0; i < input.length(); i++) {
if(input.charAt(i) == '('){
stack.push(')');
}else if(input.charAt(i) == ')'
&& !stack.isEmpty() && stack.peek() == ')'){
stack.pop();
}else if(stack.isEmpty()){
return false;
}
}
if(!stack.isEmpty()){
return false;
}
return true;
}
}
方法二: 剪枝,下探时只下探满足题意的分支
public class Solution {
/**
* @param n: n pairs
* @return: All combinations of well-formed parentheses
* we will sort your return value in output
*/
public List<String> generateParenthesis(int n) {
// write your code here
List<String> result = new ArrayList<>();
generate(0, 0, n, "", result);
return result;
}
/**
*@param left: 当前层左括号个数
*@param right: 当前层右括号个数
*@param n: 输入的最大括号数
*@param s: 上一层组装的括号串
*@param result: 结果集
*/
private void generate(int left, int right, int n, String s, List<String> result){
if(left == n && right == n){
result.add(s);
return;
}
//处理当前层状态
//以左括号下探
if(left < n){
String s1 = s +"(";
generate(left+1, right, n, s1, result);
}
//以右括号下探
//此处不需要加上 && right < n,
//因为left < n时,left才会加1,因此left <= n, 所以right<left就满足right < n
if(left > right){
String s2 = s + ")";
generate(left, right + 1, n, s2, result);
}
}
}