题目链接:
https://leetcode.com/problems/generate-parentheses/description/
描述
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:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
代码一
/**
该题只要保证在任意的位置:左括号的数量>=右括号的数量
满足上述条件就能使得是有效的组合
**/
class Solution {
public List<String> generateParenthesis(int n) {
if(n == 0) {
return new ArrayList<>();
}
List<String> ans = new ArrayList<>();
String str = new String();
dfs(ans, str, 0, 0, n);
return ans;
}
private void dfs(List<String> ans, String str, int leftCount, int rightCount, int n) {
System.out.println(str);
if(leftCount == n && rightCount == n) {
ans.add(str);
return;
}
int tempRight = rightCount;
int tempLeft = leftCount;
if(tempRight < tempLeft && tempLeft < n) { // 如果当前右括号的数量少,并且左括号还能用,则当前既能选择左括号,又能选择右括号
str = str + '(';
leftCount++;
dfs(ans, str,leftCount, rightCount, n);
str = str.substring(0, str.length() - 1);
leftCount--;
str = str + ')';
rightCount++;
dfs(ans, str, leftCount, rightCount, n);
}else if(tempRight == tempLeft) { // 如果当前右括号的数量等于左括号的数量,则当前只能选择左括号
str = str + '(';
leftCount++;
dfs(ans, str,leftCount, rightCount, n);
} else if(tempLeft == n && tempRight < tempLeft) { // 如果当前右括号的数量少,并且左括号不能用,则当前只能选择右括号
str = str + ')';
rightCount++;
dfs(ans, str, leftCount, rightCount, n);
}
}
}
代码二
class Solution {
public List<String> generateParenthesis(int n) {
if(n == 0) {
return new ArrayList<>();
}
List<String> ans = new ArrayList<>();
String str = new String();
dfs(ans, str, 0, 0, n);
return ans;
}
private void dfs(List<String> ans, String str, int leftCount, int rightCount, int n) {
System.out.println(str);
if(leftCount == n && rightCount == n) {
ans.add(str);
return;
}
int tempRight = rightCount;
int tempLeft = leftCount;
// 如果当前右括号的数量少,并且左括号还能用,则当前既能选择左括号,又能选择右括号
if(tempRight < tempLeft && tempLeft < n) {
str = str + '(';
leftCount++;
dfs(ans, str,leftCount, rightCount, n);
str = str.substring(0, str.length() - 1);
leftCount--;
str = str + ')';
rightCount++;
dfs(ans, str, leftCount, rightCount, n);
str = str.substring(0, str.length() - 1);
rightCount--;
}else if(tempRight == tempLeft) {// 如果当前右括号的数量等于左括号的数量,则当前只能选择左括号
str = str + '(';
leftCount++;
dfs(ans, str,leftCount, rightCount, n);
str = str.substring(0, str.length() - 1);
leftCount--;
} else if(tempLeft == n && tempRight < tempLeft) {// 如果当前右括号的数量少,并且左括号不能用,则当前只能选择右括号
str = str + ')';
rightCount++;
dfs(ans, str, leftCount, rightCount, n);
str = str.substring(0, str.length() - 1);
rightCount--;
}
}
}
代码三
/**
该题只要保证在任意的位置:左括号的数量>=右括号的数量
满足上述条件就能使得是有效的组合
**/
class Solution {
public List<String> generateParenthesis(int n) {
if(n == 0) {
return new ArrayList<>();
}
List<String> ans = new ArrayList<>();
StringBuilder str = new StringBuilder();
dfs(ans, str, 0, 0, n);
return ans;
}
private void dfs(List<String> ans, StringBuilder str, int leftCount, int rightCount, int n) {
System.out.println(str);
if(leftCount == n && rightCount == n) {
ans.add(str.toString());
return;
}
if(leftCount > n || rightCount >n) {
return;
}
if(rightCount <= leftCount) {
str = str.append('(');
dfs(ans, str,leftCount + 1, rightCount, n);
str.setLength(str.length() - 1);
str = str.append(')');
dfs(ans, str, leftCount, rightCount + 1, n);
str.setLength(str.length() - 1);
}
}
}
代码四
/**
该题只要保证在任意的位置:左括号的数量>=右括号的数量
满足上述条件就能使得是有效的组合
**/
class Solution {
public List<String> generateParenthesis(int n) {
if(n == 0) {
return new ArrayList<>();
}
List<String> ans = new ArrayList<>();
StringBuilder str = new StringBuilder();
dfs(ans, str, 0, 0, n);
return ans;
}
private void dfs(List<String> ans, StringBuilder str, int leftCount, int rightCount, int n) {
System.out.println(str);
if(leftCount == n && rightCount == n) {
ans.add(str.toString());
return;
}
if(leftCount > n || rightCount >n) {
return;
}
if(rightCount <= leftCount) {
str = str.append('(');
dfs(ans, str,leftCount + 1, rightCount, n);
str.setLength(str.length() - 1);
str = str.append(')');
dfs(ans, str, leftCount, rightCount + 1, n);
}
}
}
疑问:代码一和代码二是一样的,只是差了在最后的时候,有没有重新设置为和原来的一样, 代码一和代码二都是正确的。但是,代码三和代码四也是相差在最后有没有设置为何原来一样的,但是代码三是正确的,代码四是错误的!!
解答:代码一和代码二用的是String,而string每次重载+操作符的时候,都会生成新的string,因为string是不可变的。而代码三和代码四用的是StringBuilder,每次都不会生成新的StringBuilder,因为它是可变的。由于Java是穿的引用,因此每次会修改原来的东西,但是因为String每次传递了一个新的东西,而且代码一和代码二的差别都是在最后返回的地方,因此恢不恢复现场都是一样的,而StringBuilder就不一样了,每次都是修改最开始的字符串,因此,必须修复现场。
小技巧,当不知道需不需要恢复现场时,只需要交换两次dfs的位置,如果先dfs哪个都行,则必须恢复现场!!