理解多递归调用的应用场景——有效括号组合递归实现问询
基于递归复用子问题的有效括号组合生成方案
你这个利用n-1的结果来推导n的有效括号组合的思路太赞了!这其实是动态规划+递归的典型应用,核心就是靠子问题的解来构建更大问题的解。我来帮你把这个想法落地,补全代码并解释清楚细节:
核心逻辑拆解
对于n对有效括号,所有合法组合都能通过n-1的组合生成,具体方式可以理解为:
- 在n-1的每一个组合的任意位置插入一对
() - 把n-1的整个组合包裹在一对
()里(不过这种情况其实已经被上面的插入操作覆盖了——在字符串的最开头插入()就等价于包裹)
因为直接插入会出现重复的组合(比如不同的插入位置可能生成相同的字符串),所以用HashSet来自动去重,最后转成List返回更符合常见的输出需求。
完整Java代码实现
import java.util.HashSet; import java.util.ArrayList; import java.util.List; public class ValidParenthesesGenerator { // 对外暴露的方法,返回List格式的结果 public List<String> generateParenthesis(int n) { HashSet<String> resultSet = getCombinations(n); return new ArrayList<>(resultSet); } // 递归获取去重后的组合集合 private HashSet<String> getCombinations(int n) { HashSet<String> result = new HashSet<>(); // 边界处理:n<=0返回空集合,比返回null更安全,避免空指针 if (n <= 0) { return result; } // 递归终止条件:n=1时只有一种组合 if (n == 1) { result.add("()"); return result; } // 先拿到n-1的所有有效组合 HashSet<String> prevCombos = getCombinations(n - 1); // 遍历每个n-1的组合,生成新的组合 for (String combo : prevCombos) { // 在每个可能的位置插入"()" for (int i = 0; i <= combo.length(); i++) { StringBuilder sb = new StringBuilder(combo); sb.insert(i, "()"); result.add(sb.toString()); } } return result; } // 测试用例 public static void main(String[] args) { ValidParenthesesGenerator generator = new ValidParenthesesGenerator(); System.out.println(generator.generateParenthesis(2)); // 输出 [(()), ()()] System.out.println(generator.generateParenthesis(3)); // 输出 [((())), (()()), (())(), ()(()), ()()()] } }
关键细节说明
- 边界处理优化:把n<=0的返回值从null改成空集合,这样后续遍历的时候不会抛出
NullPointerException,代码鲁棒性更强。 - 去重机制:用
HashSet自动过滤重复组合,比如n=3时,不同的插入路径可能生成相同的字符串,HashSet能帮我们省去手动判重的麻烦。 - 递归逻辑:每次递归都依赖上一层的结果,逐步构建出n的所有合法组合,逻辑非常直观,容易理解和调试。
可选优化方向
如果想要提升效率,避免HashSet的额外开销,可以手动控制插入的位置,只在能生成新组合的位置插入(比如只在字符串中左括号数量>=右括号数量的位置插入,或者只在现有组合的开头、结尾以及左括号后面插入),这样可以从根源上避免重复,不过这种方式需要对有效括号的规则有更细致的理解。
内容的提问来源于stack exchange,提问作者rgamber
相关产品推荐
相关产品推荐

