题目
思路
- 思路一:我们直接使用深度优先暴力每种可能性,定义recur(String s, int l, int r),当前通过(和)产生的组合,l表示剩余未使用(,r表示剩余未使用),再加上判断剪枝掉不合理,判断条件是先使用左括号后使用右括号,因此每次递归时,必然左括号要小于等于右括号。结束条件是左右括号都使用完成即可。
- 思路二:我们知道每次(n,n)的组合依赖于(n-1,n-1)的组合,因此当我们知道(n-1,n-1)的组合,再遍历它的每个人结果进行组合,组合有2种或3种可能性:
- “(“ + s + “)
- “()” + s
- s + “()”
其中b、c可能会重复,因此我们要判断一下是否重复再添加,当(1,1)时,我们知道此时只有一种组合就是”()”这就是终止条件,错误解法,哭唧唧
代码
//1.深度优先+剪枝List<String> res = new ArrayList<>();public List<String> generateParenthesis(int n) {recur("", n, n);return res;}public void recur(String s, int l, int r) {if (l == 0 && r == 0) res.add(s);if (l < 0 || r < 0 || r < l) return;recur(s + "(", l - 1, r);recur(s + ")", l, r - 1);}//2. 动态规划,使用一维数组表示public List<String> generateParenthesis(int n) {List<String> dp = new ArrayList<>();List<String> updateDp = new ArrayList<>();dp.add("");if (n > 0) dp.set(0, "()");for (int i = 2; i <= n; i++) {for (String s : dp) {updateDp.add("(" + s + ")");String s1 = s + "()", s2 = "()" + s;updateDp.add(s1);if (!s1.equals(s2)) updateDp.add(s2);}List<String> t = updateDp;updateDp = dp;dp = t;updateDp.clear();}return dp;}//3.暴力递归产生合理括号public List<String> generateParenthesis(int n) {if (n == 0) {List<String> res = new ArrayList<>();res.add("");return res;}if (n == 1) {List<String> res = new ArrayList<>();res.add("()");return res;}List<String> list = generateParenthesis(n - 1);for (int i = list.size() - 1; i >= 0; i--) {String s = list.remove(i);list.add("(" + s + ")");String s1 = s + "()", s2 = "()" + s;list.add(s1);if (!s1.equals(s2)) list.add(s2);}return list;}
