暴力解法(Java)
核心思想: 对于n对括号,可以生成2^2n个括号组合且每个括号组合的长度为2n,逐一判断括号组合是否有效即可。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> resList = new ArrayList<>();//结果集
StringBuilder sb = new StringBuilder();//用于保存生成的括号组合
getParenthesis(sb, resList, n);//递归生成括号组合,并将有效的括号组合加入结果集
return resList;
}
//递归生成括号组合,并将有效的括号组合加入结果集
public void getParenthesis(StringBuilder sb, List<String> resList, int n){
if(sb.length() == 2 * n && isValid(sb))//长度为2n且有效
resList.add(sb.toString());
if(sb.length() < 2 * n){//同一位置既可以生成左括号“(”,也可以生成右括号“)”
sb.append('(');//生成左括号
getParenthesis(sb, resList, n);
sb.deleteCharAt(sb.length() - 1);
sb.append(')');//生成右括号
getParenthesis(sb, resList, n);
sb.deleteCharAt(sb.length() - 1);
}
}
//对生成的括号组合的有效性进行判断
public boolean isValid(StringBuilder sb) {
int count = 0;//count=0表示有效的括号组合
for(int i = 0; i < sb.length(); i++){
if(sb.charAt(i) == '(')
count++;
else
count--;
if(count < 0)//右括号多于左括号
return false;
}
return count == 0;
}
}
回溯解法(Java)
核心思想: 上述解法中,任意位置都可以生成左括号“(”或者是右括号“)”,但实际上并非如此,左括号和右括号最多有n个,并且当前的括号组合中左括号数必须小于或等于右括号数,因此,如果当前的括号组合中的左括号数leftCount小于n,则可以生成左括号;如果当前的括号组合中的右括号数rightCount小于左括号数leftCount,则可以生成右括号。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> resList = new ArrayList<>();//结果集
StringBuilder sb = new StringBuilder();//用于保存生成的括号组合
getParenthesis(sb, resList, 0, 0, n);//递归生成括号组合,并将有效的括号组合加入结果集
return resList;
}
//生成括号组合,并将有效的括号组合加入结果集
public void getParenthesis(StringBuilder sb, List<String> resList, int leftCount, int rightCount, int n){
//如果当前的括号组合中,左括号数leftCount等于右括号数rightCount且等于n
if(leftCount == n && rightCount == n)
resList.add(sb.toString());
//如果当前的括号组合中的左括号数leftCount小于n
if(leftCount < n){
sb.append('(');//生成左括号
getParenthesis(sb, resList, leftCount + 1, rightCount, n);
sb.deleteCharAt(sb.length() - 1);
}
//如果当前的括号组合中的右括号数rightCount小于左括号数leftCount
if(rightCount < leftCount){
sb.append(')');//生成右括号
getParenthesis(sb, resList, leftCount, rightCount + 1, n);
sb.deleteCharAt(sb.length() - 1);
}
}
}
动态规划
核心思想: n对括号生成的有效括号组合可以用(a)b来表示,其中a和b分别是一个有效的括号组合(可以为空),即a为p对括号生成的有效括号组合,b为q对括号生成的有效括号组合,且p+q=n-1,遍历a和b的所有可能性并拼接,即可得到n对括号生成的有效括号组合。
其中p + q = n - 1
class Solution {
public List<String> generateParenthesis(int n) {
List<String>[] dp = new List[n + 1];//记录f0~fn有效括号组合,其中fn表示n对括号生成的有效括号组合
dp[0] = Arrays.asList("");//f0=[""]
for (int i = 1; i <= n; i++) {
dp[i] = new ArrayList<>();//i对括号生成的有效括号组合
for (int p = 0; p < i; p++) {//p = 0 ~ i - 1,则q = i - 1 - p
for (String a : dp[p]) {//a为p对括号生成的有效括号组合
for (String b : dp[i - 1 - p]) {//b为q对括号生成的有效括号组合
dp[i].add("(" + a + ")" + b);//拼接a和b的所有可能性
}
}
}
}
return dp[n];
}
}