题目链接:https://leetcode.cn/problems/generate-parentheses/
![](https://i-blog.csdnimg.cn/blog_migrate/7159a8c7dd6d2af068fc63aa0e010bab.png)
解题思路:递归,找出所有左括号和右括号的组合,然后判断每种组合是否是有效的
定义递归函数:
void solver(List<String> answer, String tem, int leftNum, int rightNum)
递归函数的功能:当前使用一个左括号或者右括号进行组合,因为长度为n的序列就是在长度为n-1的序列后面加上一个"("或者")",tem保存组合的结果,如果是一种有效的组合,将将结果保存在answer中。leftNum和rightNum左括号和右括号剩余的数量
递归的终止条件
如果leftNum=0&&rightNum=0,说明已经组成了n对括号
如果n对括号是一种有效组合,就将tem加入到answer中
如果leftNum!=0,说明还有左括号可以用,使用一个左括号进行组合 s1=tem+"(",然后递归的进行求解solver(answer,s1,leftNum-1,rightNum)
如果rightNum!=0,说明还有右括号可以用,使用一个右括号进行组合s2=tem+")",然后递归的求解solver(answer,s2,leftNum,rightNum-1)
否则,说明leftNum==0,没有左括号,只有右括号
当前只能选择右括号进行组合 s1=tem+")",然后递归的求解solver(answer,s1,leftNum,rightNum-1)
判断是否是一种有效组合,使用栈来判断n对括号的组合是否是一种有效组合,
遇到 "(" 就入栈,遇到 ")" 时,如果栈顶元素不是"(",返回false,否则栈顶元素出栈
如果最后栈中没有元素,返回true,否则返回false
AC代码
class Solution {
public static List<String> generateParenthesis(int n) {
List<String> answer = new ArrayList<>();
solver(answer,"",n,n);
return answer;
}
public static void solver(List<String> answer, String tem, int leftNum, int rightNum) {
if (leftNum == 0 && rightNum == 0) {
if (isMatch(tem)) {
answer.add(tem);
}
return;
}
if (leftNum!=0){
String s1 = tem+"(";
solver(answer,s1,leftNum-1,rightNum);
if (rightNum!=0){
String s2 = tem+")";
solver(answer,s2,leftNum,rightNum-1);
}
}else {
String s1 = tem+")";
solver(answer,s1,leftNum,rightNum-1);
}
}
public static boolean isMatch(String s) {
Deque<Character> stack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
stack.push(c);
} else {
if (stack.isEmpty()){
return false;
}
if (stack.peek() == '(') {
stack.pop();
}else {
return false;
}
}
}
return stack.isEmpty();
}
}
优化:
上面判断是否是一种有效的组合时使用的是栈判断,而且有很多无效的组合,因为只有一种括号,所以可以使用左右括号的数量来判断是否是一种有效的组合以及提前结束递归
如果剩余左括号"("的数量大于剩余右括号")"的数量,那么一定有左括号"("不能与右括号")"配对,这种情况下后续所有组合都是无效的,直接返回。
比如剩余2个"(" 和1个 ")",一定不是一个有效的组合,因为不论前面的组合怎么样,只要当前遇到"(",后面就需要有一个")"与之配对,而")"数量小于"(",显然不能配对
如果左括号"("的数量小于右括号")"的数量,那么当前既可以选择左括号,也可以选择右括号进行组合
如果左括号"("的数量等于右括号")"的数量,那么当前只能选择左括号,否则后续一定是不一个有效的组合,比如 "("剩余1个,")"剩余1个:
那么只能先选择"(",后选择")"才能组合成"()"
如果先选择")",后选择"(",组合的是")(",不是一种有效组合
因为直接在选择的时候排除了所有的不可能结果,所以当leftNum=rightNum==0时,当前tem就是一种有效的组合,直接添加在answer中。
AC代码:
class Solution {
public static List<String> generateParenthesis(int n) {
List<String> answer = new ArrayList<>();
solver(answer,"",n,n);
return answer;
}
public static void solver(List<String> answer, String tem, int leftNum, int rightNum) {
if (leftNum == 0 && rightNum == 0) {
answer.add(tem);
return;
}
if (leftNum>rightNum){
return;
}else if (leftNum<rightNum){
if (leftNum!=0){
String s1 = tem+"(";
solver(answer,s1,leftNum-1,rightNum);
}
if (rightNum!=0){
String s2 = tem+")";
solver(answer,s2,leftNum,rightNum-1);
}
}else {
String s1 = tem+"(";
solver(answer,s1,leftNum-1,rightNum);
}
}
}