1. 核心题目
1.1 题目描述
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
1.2 示例
条件 1 <= n <= 8
1.2.1 例1
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
1.2.2 例2
输入:n = 1
输出:["()"]
1.3 免责声明
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-to-roman
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
本题题目源自力扣,这里声明地址,不做商用,只做学习使用,特注免责。
2.题目解析
2.1 初步思考
本题如果考虑不到二叉树的话,基本就只能暴力解决了。【暴力解的结果也是一个满二叉树的排除解法】
至于为什么需要考虑二叉树,在笔者看来,有以下的原因:
- 因为每次增加括号填充的时候,只能填写左括号以及右括号。
- 需要得到所有情况的结果集,很类似于二叉树的路径。
2.2 具体思考
我们来看一下这里绘制的图 当 n = 2 的时候,我们将二岔树的情况画一下,就如下图所示:
图解: 两个数字
- 左侧代表左括号剩余的数量
- 右侧代表右括号剩余的数量
- 每一级减少的数字,代表已经添加了对应的括号了。
通过手绘如此的二叉树 我们发现填充二岔树的条件有以下几点:
- 左侧的数字大于右侧的时候 终止本条二岔树 ==> 即【左侧的数字小于等于右侧的数字】
- 两侧的的数字都大于等于0
- 当两侧数字都等于0的时候本轮就得出一个结果,将路径放入到结果集之中。
因此 依照下列思路就能完成本题的解答了。
- 需要依据左侧括号和右侧括号剩余的数量来走完所有的路径。
- 只有右括号大于等于左侧括号的时候才进行下一个结点的操作。
- 两个括号的数量都大于等于0的时候才进行下一个结点的操作。
- 当两个括号的数量都为0的时候,将路径输出到结果集之中。
- 自己的子节点的操作则为左侧计数减1 左侧括号加1;右侧计数减1 右侧括号加1。
2.3 具体编码
依据上述思路 具体得到的编码未下列编码
class Solution {
public List<String> generateParenthesis(int n) {
List<String> ret = new ArrayList(); // 存放结果值的
dfs(ret, n, n, ""); // 采用深度优先的算法 填充最终的结果
return ret;
}
/**
* 深度优先 得到符合要求的内容,并将内容存入结果集之中。
* ret: 要填充的结果表
* l_n: 左侧剩余的括号
* r_n:右侧剩余的括号
* pre: 存储当前前面的路径的方法
*/
public void dfs(List<String> ret, int l_n, int r_n, String pre){
if(l_n==0&&r_n==0){ // 左括号和右括号都没有剩余的话 则填充ret即可
ret.add(pre);
}else if(l_n<=r_n&&l_n>=0){ // 注意:右边的剩余括号数量要大于左边剩余括号的数量才合法 左侧的括号数量也不能小于0
dfs(ret, l_n-1, r_n, pre+"("); // 填充左括号的情况 【左侧计数-1,左侧加括号】
dfs(ret, l_n, r_n-1, pre+")"); // 填充右括号的情况 【右侧计数-1, 右侧加括号】
} // 其他的情况都非法
}
}