LeetCode热题100--39. 组合总和

题目

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:

输入:candidates = 2,3,6,7, target = 7

输出:\[2,2,3,7]

解释:

2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。

7 也是一个候选, 7 = 7 。

仅有这两种组合。

示例 2:

输入: candidates = 2,3,5, target = 8

输出: \[2,2,2,2,2,3,3,3,5]

示例 3:

输入: candidates = 2, target = 1

输出: \[\]

题解

java 复制代码
class Solution {
    void backtrack(List<Integer> state, int target, int[] choices, int start, List<List<Integer>> res) {
        // 子集和等于 target 时,记录解
        if (target == 0) {
            res.add(new ArrayList<>(state));
            return;
        }
        // 遍历所有选择
        // 剪枝二:从 start 开始遍历,避免生成重复子集
        for (int i = start; i < choices.length; i++) {
            // 剪枝一:若子集和超过 target ,则直接结束循环
            // 这是因为数组已排序,后边元素更大,子集和一定超过 target
            if (target - choices[i] < 0) {
                break;
            }
            // 尝试:做出选择,更新 target, start
            state.add(choices[i]);
            // 进行下一轮选择
            backtrack(state, target - choices[i], choices, i, res);
            // 回退:撤销选择,恢复到之前的状态
            state.remove(state.size() - 1);
        }
    }

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<Integer> state = new ArrayList<>(); // 状态(子集)
        Arrays.sort(candidates); // 对 candidates 进行排序
        int start = 0; // 遍历起始点
        List<List<Integer>> res = new ArrayList<>(); // 结果列表(子集列表)
        backtrack(state, target, candidates, start, res);
        return res;
    }
}

解析

出自:39. 组合总和(回溯,清晰图解)

java 复制代码
class Solution {
    // backtrack函数接收5个参数:state(状态),target,choices(选择),start和res(结果)。这是一个回溯函数。
    void backtrack(List<Integer> state, int target, int[] choices, int start, List<List<Integer>> res) {
        // 如果目标值减去任意选择的元素之和等于0,则找到了解(一个可能的和为目标值的组合)。
        if (target == 0) {
            // 将当前状态(即子集)添加到结果列表中。
            res.add(new ArrayList<>(state));
            return;
        }
        
        // 遍历所有选择可能性,确保没有重复的组合。start参数用于这个目的。
        for (int i = start; i < choices.length; i++) {
            // Prune1: 如果选定的数字大于剩余目标值(即超出目标值),则退出循环以避免生成不相关的组合(剪枝优化)。
            if (target - choices[i] < 0) {
                break;
            }
            
            // 做出选择:将当前候选数字添加到状态中。
            state.add(choices[i]);
            
            // 递归:在剩余的目标值上调用backtrack,更新start索引以防止生成重复组合。
            backtrack(state, target - choices[i], choices, i, res);
            
            // 回溯/撤销选择:由于for循环内的递归会处理更大的和(即更深的树状图中未涵盖的数字),所以通过移除最后添加的数字来"向后",并回到状态。在这里移除最后一个元素是因为我们不再需要它了------对于子集来说,使用i而不是state.length-1是为了保持相同深度遍历树但向上层移动。
            state.remove(state.size() - 1);
        }
    }

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        // 创建一个状态列表来存储我们当前的解(子集/组合)。
        List<Integer> state = new ArrayList<>();
        
        // 将candidates数组进行排序以便于剪枝优化,使循环更高效。
        Arrays.sort(candidates);
        
        // start用于我们从哪个索引开始选取候选数字。它被初始化为0(从起点开始),但递归调用时可能会发生变化。
        int start = 0;
        
        // 创建一个列表来存储所有可能的组合及其对应的答案。
        List<List<Integer>> res = new ArrayList<>();
        
        // 从起点到末尾遍历candidates数组中可用的数字,以找出满足特定和目标的组合(通过回溯来检测所有这样的组合)。
        backtrack(state, target, candidates, start, res);

        // 返回有效选择/有效的解列表中的解答的结果。
        return res;
   <|begin▁of▁sentence|>
相关推荐
Zane1994几秒前
比较排序跑不出O(nlogn)是数学上证明过的,计数、桶、基数排序凭什么能绕开这堵墙
算法·排序算法
tiger8652 分钟前
大语言模型面试和题解,梳理中国主流开源 LLM 系列的发展脉络、技术路线与工程取舍
人工智能·gpt·深度学习·算法·自然语言处理·面试·transformer
我不会起名字32215 分钟前
一天一道力扣Hot100(36):深度优先算法---组合总和
数据结构·c++·后端·python·算法·go
虚无的纽扣41 分钟前
【力扣刷题】第三天:有效三角形的个数、快乐数
算法·排序算法
tiger8651 小时前
大语言模型面试和题解,Context Engineering 怎么做?长 Prompt、动态上下文与 Memory 管理
人工智能·深度学习·算法·语言模型·自然语言处理·面试·nlp
不会就选b1 小时前
算法日常・每日刷题--<贪心>17
算法
yuanxi2001 小时前
上药集团药品销售公司签署沪明医疗数链协议:PSS⁵视角下的跨区域数据合作机会
职场和发展·创业创新·学习方法
随便发挥4 小时前
Leetcode 剑指 Offer II 186. 文物朝代判断
leetcode
6Hzlia4 小时前
【Classic 150 刷题计划】 LeetCode 205. 同构字符串 | C++ 双向绑定与哈希表映射
c++·算法·leetcode
有点。10 小时前
C++03阶段练习(练习题)
数据结构·算法·图论