刷刷刷 Day 27 | 39. 组合总和
39. 组合总和
LeetCode题目要求
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
示例
输入:candidates = [2,3,6,7], target = 7 输出:[[2,2,3],[7]] 解释: 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。 7 也是一个候选, 7 = 7 。 仅有这两种组合。
解题思路
类似组合求法,但是又有不同之处,这里没有对深度的限制,是通过一个变向的 target 做了深度的限制。
这题比较类似于我们做过的 n 数之和。做 n 数之和时我们通常会做过排序,然后再继续找符合条件的值。
这里也可对给定的数组排序,能有效减少递归次数。
同时本题可重复使用元素,那么再每次广度遍历的时候,我们不能像处理组合那样要变化 startIndex,它需要和 循环中的 i 保持住。
上代码
class Solution { private List<List<Integer>> res = new ArrayList<>(); private Deque<Integer> path = new LinkedList<>(); public List<List<Integer>> combinationSum(int[] candidates, int target) { // 由于可使用重复元素计算和,排序后可将元素本身>target 及 sum>target 的就都过滤了,后面就不考虑了 Arrays.sort(candidates); // 回溯递归函数 backtracking(candidates, target, 0, 0); return res; } /** * candidates: 整数数组; target: 目标和;startIndex:数组那个元素开始,是变化的;sum:临时计算元素和 */ private void backtracking(int[] candidates, int target, int startIndex, int sum){ // 终止/剪枝 临时累加和已经大于 目标,那么就 return if (sum > target) { return; } // 找到目标值,并存储 if (sum == target) { res.add(new ArrayList<>(path)); return; } for (int i = startIndex; i < candidates.length; i++) { // 剪枝 if (sum > target) { break; } // 记录元素 path.add(candidates[i]); // 计算和 sum += candidates[i]; // 递归,由于可重复使用元素, startIndex 仍然使用 i backtracking(candidates, target, i, sum); // 回溯操作 sum -= candidates[i]; path.removeLast(); } } }
附:学习资料链接
分类:
算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了