【LeetCode 热题100】回溯:括号生成 & 组合总和(力扣22 / 39 )(Go语言版)

🔥 回溯专题:括号生成 & 组合总和(LeetCode 22 & 39)

LeetCode 回溯经典题:

  • 22. 括号生成
  • 39. 组合总和

这两道题都考察了回溯算法的剪枝与路径构造能力


🧩 一、22. 括号生成

📌 题目描述

给你一个整数 n,请你生成所有由 n 对括号组成的有效括号组合。

🔍 示例

text 复制代码
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

💡 解题思路

这是一道典型的回溯搜索问题,我们通过维护左右括号的使用数量来构造合法的组合。

✅ 回溯核心逻辑:
  • 初始状态:left = 0, right = 0

  • 分支选择:

    • 如果 left < n:可以添加 '('
    • 如果 right < left:可以添加 ')'
  • 当左右括号都用完(即 left == right == n)时,将当前路径加入结果集。

📦 Go 实现
go 复制代码
func generateParenthesis(n int) []string {
    var res []string
    var backtrack func(path string, left, right int)

    backtrack = func(path string, left, right int) {
        if len(path) == 2*n {
            res = append(res, path)
            return
        }
        if left < n {
            backtrack(path+"(", left+1, right)
        }
        if right < left {
            backtrack(path+")", left, right+1)
        }
    }

    backtrack("", 0, 0)
    return res
}

⚠️ 注意事项

  • 不允许 right > left,否则括号会不合法;
  • 剪枝条件写清楚,否则可能生成不合法组合或死递归。

🎯 二、39. 组合总和

📌 题目描述

给你一个无重复正整数数组 candidates ,和一个目标整数 target,找出所有可以使数字和为 target 的组合。 每个数可以重复使用无限次。

🔍 示例

text 复制代码
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]

💡 解题思路

这是标准的回溯 + 剪枝问题 ,本质是一个组合问题。

✅ 回溯核心逻辑:
  • 状态参数:当前组合 path,当前总和 sum,起始索引 start

  • 分支选择:遍历 candidates[i],每次可选择当前元素或后面的元素(允许重复选择)

  • 剪枝策略:

    • 若 sum > target,剪枝;
    • 若 sum == target,添加结果;
    • 若 sum < target,继续递归。
📦 Go 实现
go 复制代码
func combinationSum(candidates []int, target int) [][]int {
    var res [][]int
    var path []int

    var dfs func(start, sum int)
    dfs = func(start, sum int) {
        if sum == target {
            temp := make([]int, len(path))
            copy(temp, path)
            res = append(res, temp)
            return
        }
        if sum > target {
            return
        }

        for i := start; i < len(candidates); i++ {
            path = append(path, candidates[i])
            dfs(i, sum + candidates[i]) // 可重复使用同一个数
            path = path[:len(path)-1]   // 回溯
        }
    }

    dfs(0, 0)
    return res
}

⚠️ 注意事项

  • 每层递归都从当前索引 start 开始,确保可以重复选择元素;
  • 注意剪枝时不要提前跳过合法路径;
  • 每次递归完后必须回溯清除最后一个元素。

🧠 总结与对比

特性 括号生成(22) 组合总和(39)
技巧类型 回溯 + 状态剪枝 回溯 + 剪枝 + 组合
路径构建逻辑 括号平衡 + 左右限制 数组和满足目标
剪枝条件 right <= left,括号合法 sum <= target
是否可重复选择 否 是
输出顺序 所有合法括号 所有合法组合

这两道题分别属于回溯算法中常见的「字符串构造类问题 」与「数字组合类问题」。


📘 结语

  • 回溯是一种通过「递归试探 + 状态恢复」来寻找所有可行解的方法;
  • 掌握回溯的关键在于明确:路径、选择列表、结束条件与剪枝逻辑;

相关推荐
在所不辞兄几秒前
分层PINN提升多物理场一致性
人工智能·神经网络·算法·机器学习·工程仿真
wanderist.2 分钟前
CSP 第43次认证 T4:集合划分 —— 图染色与二分图判定
算法·图论
不做无法实现的梦~5 分钟前
基于 PX4 的全仓库架构、无人机算法解析与开发学习规划
算法·架构·无人机
做cv的小昊11 分钟前
【大模型算法自学笔记01】NLP基础知识(1.1 自注意力)
人工智能·笔记·算法·自然语言处理·大模型·llm
stolentime36 分钟前
AT_arc182_a [ARC182A] Chmax Rush!题解
数据结构·c++·算法·动态规划
longlongzihan37 分钟前
LeetCode 189. 轮转数组:从直观模拟到最优原地算法
c++·算法·leetcode
爱喝热水的呀哈喽42 分钟前
cpp二分库函数 lambda捕获
算法
longlongzihan1 小时前
LeetCode 76. 最小覆盖子串:滑动窗口算法详解
算法·leetcode·滑动窗口
怕浪猫10 小时前
RAG 面试 6 连问,从原理到优化全部覆盖
python·算法·面试
无线通信科研笔记10 小时前
IEEE TVT 2026 论文精读与完整复现|相位误差如何重塑近场 RIS 的幅相响应
论文阅读·人工智能·python·算法·论文笔记