数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合
https://leetcode-cn.com/problems/generate-parentheses/
示例1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
Java解法
思路:
看起来有点懵逼,但实际上是一个可细化的操作,可以看成,一对括号与上一次操作的各种排列组合,中间()()这种操作或出现重复所有会少一个,所以细化后的思路
我果然太年轻,前一轮无效不代表后一轮无效,对结果瞎了我的眼先算最小,将最小的结果带入下一轮- 来句教训,做不来的时候千万不要死磕,搞得递归都不会写了
- 参考官方解的暴力解,写出能运行的答案,递归计算所有可能组合,添加时计算有效性
- 再加上回溯控制
package sj.shimmer.algorithm;
import java.util.ArrayList;
import java.util.List;
/**
* Created by SJ on 2021/2/8.
*/
class D15 {
public static void main(String[] args) {
System.out.println(generateParenthesis(4));
}
public static List<String> generateParenthesis(int n) {
List<String> strings = new ArrayList<>();
if (n == 0) {
strings.add("()");
return strings;
}
char[] chars = new char[n * 2];
get(strings, chars, 0);
System.out.println(strings);
strings.clear();
backtrack(strings,chars,0,0);
System.out.println(strings);
return strings;
}
private static void get(List<String> strings, char[] chars, int index) {
if (index >= chars.length) {
int balance = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i]=='(') {
balance++;
}else {
balance--;
}
if (balance<0) {
break;
}
}
if (balance==0) {
strings.add(new String(chars));
}
return;
}
chars[index]='(';
get(strings,chars,index+1);
chars[index]=')';
get(strings,chars,index+1);
}
private static void backtrack(List<String> strings, char[] chars, int index,int leftNum) {
if (index >= chars.length) {
int balance = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i]=='(') {
balance++;
}else {
balance--;
}
if (balance<0) {
break;
}
}
if (balance==0) {
strings.add(new String(chars));
}
return;
}
chars[index]='(';
backtrack(strings,chars,index+1,leftNum+1);
if (leftNum>index/2) {
chars[index]=')';
backtrack(strings,chars,index+1,leftNum);
}
}
}
官方解
-
暴力解
参考上方
- 时间复杂度: O(2^2n*n)
- 空间复杂度:O(n)
-
回溯
思路如上,但加入有效控制,在进入下一次调用之前,记录有效性相关参数(已有左括号数量),与官方解写法稍不一致,但同样可用