组合总和II(力扣40)

发布于:2025-02-10 ⋅ 阅读:(74) ⋅ 点赞:(0)

这道题的难点就在于题目所给的集合中有重复的数字,我们需要进行去重操作。首先明确去重指的是去重哪一部分。注意并不是对递归的集合去重,而是对当前集合的遍历进行去重。这么说可能有点抽象,举个例子:假设集合为1,1,2,3,4,我们第一次选1,递归集合时,我们仍可以选择第二个1。但是在第一次选第二个1时,在往下选,就会出现很多与第一次选第一个1时相同的组合。所以在每一层递归函数的for循环中我们需要进行去重。不过,我们需要判断这个重复出现的数字是在当前这层递归的for循环中还是在下一层递归的for循环中。于是,我们创建了一个数组,标识这些集合中的数字是否被使用过,如果被使用过,说明是在上一层递归中被使用,如果没有被使用,说明是在当前这一层递归的for循环中。大家可以结合我下面的代码及详细注释理解。

代码及详细注释如下:

class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& candidates,int target,int sum,int start,vector<int>& used){
            //剪枝
            if(sum > target){
                return;
            }
            //终止条件
            if(sum == target){
                result.push_back(path);
                return;
            }

            for(int i = start;i < candidates.size();i++){
                //去重
                if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == 0){
                    continue;
                }
                path.push_back(candidates[i]);
                sum += candidates[i];
                used[i] = 1;
                backtracking(candidates,target,sum,i + 1,used);
                //回溯
                path.pop_back();
                sum -= candidates[i];
                used[i] = 0;
            }
            return;
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        //创建一个数组,该数组下标对应集合中元素的下标,表示集合中各个下标对应的数字有没有使用过
         vector<int> used(candidates.size(),0);

        sort(candidates.begin(),candidates.end());
        backtracking(candidates,target,0,0,used);
        return result;
    }
};


网站公告

今日签到

点亮在社区的每一天
去签到