当前位置: 首页 > news >正文

回溯——括号生成

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

生成有效括号组合
这道题是经典的回溯算法题目,核心思路是:通过递归尝试添加/右括号,始终保证在左括号数量>=右括号数量,最终生成所有合法组合。

核心逻辑讲解

  1. 回溯算法:递归尝试所有可能的括号组合,遇到无效组合直接回溯(不继续递归)。
  2. 两个关键规则(保证括号有效):
    左括号数量不能超过n(最多只能用n个左括号);
    右括号数量必须小于左括号数量(避免出现())这种无效组合)。
  3. 终止条件:当字符串长度等于2*n时,说明左右括号都用完了,直接加入结果集。

执行流程(以n=2为例)

  1. 初始:current = "",open = 0,close = 0
  2. 加左括号 -> "(",1,0
  3. 再加左括号 -> "((",2,0
  4. 只能加右括号->"(()",2,1
  5. 再加右括号->"(())",2,2(长度 = 4,加入结果)
  6. 回溯,尝试另一条路径->"()",1,1
  7. 加左括号->"()(",2,1
  8. 加右括号->"()()",2,2(加入结果)

最终得到["(())","()()"]。
总结

  1. 回溯算法递归生成所有组合,通过两个规则过滤无效括号;
  2. 时间复杂度:O(n+11​C2nn​)(卡特兰数,有效组合的总数)
  3. 空间复杂度:O(n)(递归栈深度,最多递归 2n 层)

条件 1:open < n
保证左括号不超过 n 个。
条件 2:close < open
保证右括号永远不会比左括号多,避免出现 ()) 这种无效情况。

绝对不能用close < n 代替 close < open!
必须时刻保证左括号数量大于等于右括号数量,如果条件替换成close<n,会出现以下情况:

假设n = 2
(),此时open = 1,close = 1

  1. 前面已经处理了"()()"和"(())"两种情况,先"(())",后"()()"
  2. 回溯退回到()(这一层,由于这一层的两个if都执行完了->也return
  3. 回溯到()这一层,由这一层上一次递归的场景是()( 可知执行的是添加左括号的递归,因此接下来执行的是4. 右括号的递归,此时close<n,执行右括号的递归,())
  4. 再进入())这一层的递归,由于open<n执行左括号的递归,最终result结果为"())(",出现了括号匹配错误的情况。

综上可知,为了避免出现这种括号错误匹配的问题,我们需要时刻保持左括号的数量大于等于右括号的数量,即close<open,这样当递归回溯到()时,由于close并不小于open的数量,因此不会进入执行())的递归

完整Java代码实现如下:

import java.util.ArrayList;
import java.util.List;

public class GenerateParentheses {

public List<String> generateParenthesis(int n) {// 存储最终结果List<String> result = new ArrayList<>();// 回溯递归:当前字符串、左括号数、右括号数、目标对数、结果集backtrack("", 0, 0, n, result);return result;
}/*** 回溯核心方法* @param current 当前拼接的括号字符串* @param open 已使用的左括号数量* @param close 已使用的右括号数量* @param n 目标括号对数* @param result 结果集合*/
private void backtrack(String current, int open, int close, int n, List<String> result) {// 递归终止条件:字符串长度 = 2*n(左右括号都用完了)if (current.length() == 2 * n) {result.add(current);return;}// 1. 可以添加左括号:左括号数量 < nif (open < n) {backtrack(current + "(", open + 1, close, n, result);}// 2. 可以添加右括号:右括号数量 < 左括号数量(保证有效)if (close < open) {backtrack(current + ")", open, close + 1, n, result);}
}// 测试示例
public static void main(String[] args) {GenerateParentheses solution = new GenerateParentheses();// 测试 n=3System.out.println(solution.generateParenthesis(3));// 输出:["((()))","(()())","(())()","()(())","()()()"]
}

}

http://www.jsqmd.com/news/766173/

相关文章:

  • 深度探索DIY Layout Creator:开源电路设计工具的设计哲学与创作实践
  • 无人机/机器人工程师必看:四元数姿态控制中,误差四元数到底该怎么算?
  • 终极ESP32开发指南:从零到物联网项目的完整解决方案
  • 抖音无水印批量下载器:免费获取高清视频、图集与音乐的终极指南
  • 保姆级教程:手把手教你用PMCSR寄存器配置PCIE设备的D-State(附状态迁移流程图)
  • 初创团队在虚拟服务器上通过Taotoken低成本使用多模型能力
  • 5分钟完成FF14国际服汉化:开源中文补丁完全指南
  • MCP 2026医疗数据防护落地指南:5步完成等保2.0+GB/T 39725双标适配,附卫健委备案自查清单
  • 用户如何挑选国内靠谱的二氧化碳培养箱企业?2026年实测方案 - 速递信息
  • Windows 安全中心不等于杀毒软件 ≠ 反间谍程序 ≠ 防火墙
  • 告别if-else混乱:用行为树重构你的ROS2机器人决策逻辑(以Nav2恢复机制为例)
  • 为Claude Code配置Taotoken作为自定义模型供应商的详细指南
  • 太香了!CSS选择器复合玩法+常用属性一网打尽
  • WarcraftHelper:让魔兽争霸3在现代电脑重获新生的终极兼容性修复方案
  • 从零构建命令行体重管理工具:CLI设计、数据持久化与Python实践
  • 3步掌握dedao-dl:打造个人专属知识资产管理系统
  • mysql 解释说明 sqlite里1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5
  • DsHidMini:让PS3控制器在Windows上重获新生的终极解决方案
  • 多模态大模型在社交场景中的交互能力评估与优化
  • 基于文本与CLI构建个人知识管理系统:从aspenkit/aspens实践到效率革命
  • 通俗数学7-质子三夸克的算法
  • 2026-05-06
  • 避坑指南:RobotStudio中ABB机器人Socket通讯的3个常见错误与排查方法(IP/端口/绑定)
  • 2026年实测!为上海用户推荐靠谱的二氧化碳培养箱生产工厂 - 速递信息
  • 告别卡死!STM32 HAL库中断处理中安全延时的三种替代方案(非阻塞式)
  • Android车载开发中的蓝牙、WiFi与NFC技术深度解析
  • w3x2lni:魔兽地图格式转换与数据修复的技术实现深度解析
  • 如何构建个人数字记忆库:WeChatMsg聊天记录永久保存完全指南
  • Claude Code Harness Engineering介绍(Agent = Model + Harness 模型提供智力,Harness(马具/控制系统) 提供控制、可靠性和生产力)多代理协作
  • 实测!国内正规超声波细胞破碎仪生产商推荐给科研工作者 - 速递信息