【Leetcode】22. 括号生成

79 阅读2分钟

题目描述

在这里插入图片描述


// 22. 括号生成

// 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且
// 有效的 括号组合。

题解

// 回溯搜索法
// 
// 想到方法不难,难的是如何设定左右括号添加的关系,特别是什么时候加(停止加)右括号。
// 初始化答案保存位res,特殊情况判断,如果n为0。直接返回空res。
// 定义一个StringBuilder cur,用来保存组合出来的String括号排列,
// 递归调用回溯搜索函数backtrack。最后返回res。
// 
// 定义回溯搜索函数backtrack,输入为括号排列保存参数cur,左括号出现次数left,
// 右括号出现次数right,括号排列总组数max(max为常数n,表示总共有n对括号),
// 所以每个排列结果的长度一定为max * 2。
// 定义递归终止条件,如果cur排列的长度等于max * 2,将StringBuilder转为字符串存入
// res中,并返回(回溯)。
// if条件判断:如果左括号出现次数left小于max,将一个左括号填入cur,递归调用
// backtrack,此时函数输入的left变为left+1,即左括号出现次数计数一次。
// 回溯之后的下一句需要删掉cur的末端括号字符,用来回溯排列其他情况。
// 第二个if条件判断关于右括号:和左括号不同,右括号必须和左括号成双成对出现,
// 因此if触发条件为:右括号出现次数如果小于左括号出现次数 right < left,
// 将一个右括号填入cur中,并递归调动backtrack,函数输入的right为right+1,
// 回溯后的下一句为将cur的末端括号字符删除一个,用来回溯排列其他情况。
//
// 执行用时:1 ms, 在所有 Java 提交中击败了96.38%的用户
// 内存消耗:38.5 MB, 在所有 Java 提交中击败了77.08%的用户
import java.util.ArrayList;
class Solution {
	List<String> res = new ArrayList<>();
    public List<String> generateParenthesis(int n) {
        if (n == 0)
            return res;
		StringBuilder cur = new StringBuilder();
        backtrack(cur, 0, 0, n);
        return res;
    }
	
	private void backtrack(StringBuilder cur, int left, int right, int max) {
		if (cur.length() == max * 2) {
			res.add(cur.toString());
			return;
		}
		if (left < max) {
			cur.append("(");
			backtrack(cur, left + 1, right, max);
			cur.delete(cur.length() - 1, cur.length());
		}
		if (right < left) {
			cur.append(")");
			backtrack(cur, left, right + 1, max);
			cur.delete(cur.length() - 1, cur.length());
		}
	}
}



// 优化版本
// 执行用时:1 ms, 在所有 Java 提交中击败了96.38%的用户
// 内存消耗:38.4 MB, 在所有 Java 提交中击败了93.82%的用户
import java.util.ArrayList;
class Solution {
	List<String> res = new ArrayList<>();
    public List<String> generateParenthesis(int n) {
        if (n == 0)
            return res;
        backtrack("", 0, 0, n);
        return res;
    }
	
	private void backtrack(String cur, int left, int right, int max) {
		if (cur.length() == max * 2) {
			res.add(cur);
			return;
		}
		if (left < max) {
			backtrack(cur + "(", left + 1, right, max);
		}
		if (right < left) {
			backtrack(cur + ")", left, right + 1, max);
		}
	}
}