【力扣40】组合总和II
题目
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
**注意:**解集不能包含重复的组合。
示例 1:
1 | 输入: candidates = [10,1,2,7,6,1,5], target = 8, |
示例 2:
1 | 输入: candidates = [2,5,2,1,2], target = 5, |
提示:
1 <= candidates.length <= 1001 <= candidates[i] <= 501 <= target <= 30
实现代码
使用DFS实现回溯算法 + 排序 + 剪枝
1 | class Solution { |
核心思路
这道题的关键在于去重,因为数组中可能包含重复元素,但最终结果不能有重复的组合。
解决方案:
- 排序:将相同的元素聚集在一起,便于去重处理
- 去重逻辑:
if (i > start && candidates[i] == candidates[i - 1]) continue;- 在同一层递归中,跳过重复的元素
- 但在不同层递归中,允许使用重复元素
- 剪枝优化:
- 当前和超过target时直接返回
- 当前元素加上已有和超过target时,后续更大元素也不用考虑(因为已排序)
时间复杂度
在最坏情况下,需要遍历所有可能的组合。假设candidates大小为n:
状态空间:理论上最多有
2^n种子集组合实际剪枝效果:
- 排序后的剪枝:当
sum + candidates[i] > target时直接break,避免后续更大元素的尝试 - target限制:只有和等于target的组合才会被加入结果
- 去重逻辑:跳过同层重复元素,减少无用搜索
- 排序后的剪枝:当
每个有效状态的处理时间:复制当前路径到结果集,时间复杂度为
O(k),其中k为当前路径长度
因此,总的时间复杂度为O(k × 2^n),其中k为平均路径长度。但由于剪枝优化,实际运行时间会显著优于这个上界。
空间复杂度
主要的额外空间消耗来自:
result:存储所有符合条件的组合。由于target限制,有效组合数量远少于2^n,具体数量取决于输入数据path:递归过程中存储当前路径,最大深度为n(最坏情况下所有元素都选中),空间复杂度为O(n)- 递归调用栈:最大深度为
n,空间复杂度为O(n)
因此,如果不计算输出结果的存储空间,额外空间复杂度为O(n)。包含输出结果时,空间复杂度取决于有效组合的数量和平均长度。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 青柠!
评论


















































