题目地址:Generate Parentheses
描述:
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
大意:给你n组圆括号,写出符合规则的方法,规则如下面的例子。
相关知识点:
[借鉴链接](https://www.cnblogs.com/smuxiaolei/p/7505391.html)
⭕️ 递归是一种算法结构,回溯是一种算法思想。
⭕️ 一个递归就是在函数中调用函数本身来解决问题。
⭕️ 回溯就是通过不同的尝试来生成问题的解,有点类似于穷举,但是和穷举不同的是回溯会“剪枝”。
⭕️ 回溯搜索是深度优先搜索(DFS)的一种,对于某一个搜索树来说(搜索树是起记录路径和状态判断的作用),回溯和DFS,其主要的区别是,回溯法在求解过程中不保留完整的树结构,而深度优先搜索则记下完整的搜索树。
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class GenerateParentheses {
public static void main(String[] args) {
//方法1:自己写的,使用的是全排列,然后筛选
// Set<String> strings = generateParenthesisDemo(4);
//方法2:摘自https://leetcode.com/problems/generate-parentheses/discuss/10100/Easy-to-understand-Java-backtracking-solution
List<String> strings = generateParenthesis(3);
System.out.println(strings);
}
private static Set<String> generateParenthesisDemo(int n) {
Set<String> res = new HashSet<>();
String[] arr = new String[2 * n];
for (int i = 0; i < 2 * n - 1; i += 2) {
arr[i] = "(";
arr[i + 1] = ")";
}
allSort(0, arr.length, arr, res);
return res;
}
//全排列然后去重并且筛选条件,使用DFS思想全部得出,然后再从中筛选中符合题目的。
private static void allSort(int sortNum, int size, String[] arr, Set<String> res) {
int zero = 0;
String ex;
//大的框架是全排列
if (sortNum == size - 1) {
StringBuffer param = new StringBuffer();
for (int i = 0; i < size; i++) {
//筛选条件:当左括号的时候zero加1
if (arr[i].equals("(")) {
zero++;
}
//当存在左括号的时候,再判断右括号。
if (zero > 0 && arr[i].equals(")")) {
zero--;
}
param.append(arr[i]);
}
if (zero == 0) {
res.add(param.toString());
}
} else {
int temp = sortNum;
while (temp < size) {
allSort(sortNum + 1, size, arr, res);
if (temp < size - 1) {
ex = arr[temp + 1];
arr[temp + 1] = arr[sortNum];
arr[sortNum] = ex;
}
temp++;
}
}
}
//方法2 回溯思想。DFS的时候进行条件的判断,当不满足时进行剪枝。
public static List<String> generateParenthesis(int n) {
List<String> list = new ArrayList<String>();
backtrack(list, "", 0, 0, n);
return list;
}
public static void backtrack(List<String> list, String str, int open, int close, int max) {
//深度等于2n的时候,结束本次搜索,退到上个节点
if (str.length() == max * 2) {
list.add(str);
return;
}
//左括号必须小于n
if (open < max)
backtrack(list, str + "(", open + 1, close, max);
//右括号需小于左括号的数目
if (close < open)
backtrack(list, str + ")", open, close + 1, max);
}
}