「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
题目描述
示例 1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"] 示例 2:
输入:n = 1 输出:["()"]
题目链接:括号生成
思路介绍
题目分析
有 n 个 "(" 和 n 个 ")",有 2n 个格子,写出所有可能的组合。
填入第1个空位后,需要考虑第2个空位需要填什么, 填入第2个空位后,需要考虑第3个空位需要填什么, 填入第3个空位后,需要考虑第4个空位需要填什么, ...
我们发现,存在相似性的子问题,那么使用递归可以解决。 在 2n 个格子填满的时候,递归终止。也就是上图中,在树的第 n 层递归终止。
那么对于一个合法的括号来说,
- 首先需要满足 包括了n个左括号n个右括号
- 其次在任意时刻左括号的个数需要大于等于右括号的个数
解题思路
任何一个括号序列都一定是由 ( 开头,并且第一个 ( 一定有一个唯一与之对应的 )。这样一来,每一个括号序列可以用 (a)b 来表示,其中 a 与 b 分别是一个合法的括号序列(可以为空)。
那么,要生成所有长度为 2 * n 的括号序列,我们定义一个函数 generate(n) 来返回所有可能的括号序列。那么在函数 generate(n) 的过程中:
我们需要枚举与第一个 ( 对应的 ) 的位置 2 * i + 1; 递归调用 generate(i) 即可计算 a 的所有可能性; 递归调用 generate(n - i - 1) 即可计算 b 的所有可能性; 遍历 a 与 b 的所有可能性并拼接,即可得到所有长度为 2 * n 的括号序列。 为了节省计算时间,我们在每次 generate(i) 函数返回之前,把返回值存储起来,下次再调用 generate(i) 时可以直接返回,不需要再递归计算。
代码
class Solution {
ArrayList[] cache = new ArrayList[100];
public List<String> generate(int n) {
if (cache[n] != null) {
return cache[n];
}
ArrayList<String> ans = new ArrayList<String>();
if (n == 0) {
ans.add("");
} else {
for (int c = 0; c < n; ++c) {
for (String left: generate(c)) {
for (String right: generate(n - 1 - c)) {
ans.add("(" + left + ")" + right);
}
}
}
}
cache[n] = ans;
return ans;
}
public List<String> generateParenthesis(int n) {
return generate(n);
}
}
运行结果
执行结果:通过
执行用时:7 ms,
内存消耗:41.7 MB
\