跳转至

40. 组合总和 II

力扣链接(中等):https://leetcode.cn/problems/combination-sum-ii

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次

注意:解集不能包含重复的组合。

示例 1:

Text Only
1
2
3
4
5
6
7
8
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

Text Only
1
2
3
4
5
6
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

提示:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

个人题解

注意一定要思考一下如何判断当前层元素是否重复使用:

C++
1
2
3
4
5
6
7
8
9
// 先排序,这样才能让相同元素相邻,方便判断
sort(candidates.begin(), candidates.end());

// ...

// 为什么要首先判断 i > begin ?
if(i > begin && candidates[i] == candidates[i - 1]) {
    continue;
}
C++
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(vector<int> &candidates, int target, int sum, int begin) {
        if(sum >= target) {
            if(sum == target) result.push_back(path);
            return;
        }

        for(int i = begin; i < candidates.size(); i++) {
            // 判断在当前层中,当前元素是否已经使用
            // i > begin 很关键,因为每往下递归一层,begin 都会 + 1(题目要求每个元素在每条路径中只能使用一次)
            // 如果不判断 i > begin,那么就会误把递归过程中 i == begin (当前层第一次遍历的情况)
            // 做 candidates[i] == candidates[i - 1] 判断,这是逻辑错误的,因为 i == begin (是当前层遍历到第一个元素)
            // 第一个元素自然不存在重复使用当前层元素的情况
            if(i > begin && candidates[i] == candidates[i - 1]) {
                continue;
            }
            path.push_back(candidates[i]);
            sum += candidates[i];
            backtracking(candidates, target, sum, i + 1);
            path.pop_back();
            sum -= candidates[i];
        }
    }

    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        // 先排序,这样才能让相同元素相邻,方便判断
        sort(candidates.begin(), candidates.end());
        backtracking(candidates, target, 0, 0);
        return result;
    }
};