liuxuhelloworld's notebook

题目链接

https://leetcode-cn.com/problems/generate-parentheses/

解答过程

动态规划

这个题目从动态规划的角度来考虑,我觉得不容易。从代码来看,还是挺好理解的,但是我觉得,如果没有相关经验,并不容易想出状态转移方程。每一个合法的括号序列可以表示为(a)b,递归的a和b都是合法的括号序列(可以为空)。

	public List<String> generateParenthesis(int n) {
		if (n <= 0) {
			return Collections.singletonList("");
		}

		if (n == 1) {
			return Collections.singletonList("()");
		}

		List<String>[] dp = new List[n+1];
		dp[0] = Collections.singletonList("");
		dp[1] = Collections.singletonList("()");
		for (int i = 2; i < dp.length; i++) {
			List<String> all = new ArrayList<>();
			for (int j = 0; j < i; j++) {
				List<String> parts1 = dp[j];
				List<String> parts2 = dp[i-1-j];

				for (String part1 : parts1) {
					for (String part2 : parts2) {
						all.add("(" + part1 + ")" + part2);
					}
				}
			}

			dp[i] = all;
		}

		return dp[n];
	}

回溯法

这个题目从回溯法的角度来考虑,从代码来看,倒是简洁很多。思路有一点讨巧,但是很好理解,很好的体现了回溯的思想。

	public List<String> generateParenthesis(int n) {
		List<String> res = new ArrayList<>();

		backtrack(res, n, n, new String());

		return res;
	}

	private void backtrack(List<String> res, int openLeft, int closeLeft, String s) {
		if (openLeft == 0 && closeLeft == 0) {
			res.add(s);
			return;
		}

		if (openLeft > closeLeft) {
			return;
		}

		if (openLeft > 0) {
			backtrack(res, openLeft-1, closeLeft, s + "(");
		}

		if (closeLeft > 0) {
			backtrack(res, openLeft, closeLeft-1, s + ")");
		}
	}