[LeetCode 40]组合总和II

本文解析了LeetCode问题40的C++解决方案,对比了两种方法:回溯+set判断唯一性和递归优化。介绍了如何使用递归实现组合总和II,通过实例展示了如何避免重复组合并提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[LeetCode 40]C++组合总和II

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

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

说明:

所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]

来源:力扣(LeetCode)
链接:https://leetcodecn.com/problems/
combination-sum-ii

优化后方法:

class Solution {
public:
    void recursive(int Pos,vector<int>& nums,int Length,int target,vector<int>& item,vector<vector<int>>& result){
        
        if(target==0){//回溯点
            result.push_back(item);
            return;
        }
        int index=Pos;//元素不同,更新
		       
        while(index<Length&&target>=nums[index]){
            
            if(index==Pos||nums[index]!=nums[index-1]){
                item.push_back(nums[index]);
        		//target不断减去当前元素
                recursive(index+1,nums,Length,target-nums[index],item,result);
                item.pop_back();//回溯弹出元素
            }
            ++index;
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int>item;
        vector<vector<int>>result;
        int Length=candidates.size();
        int Pos=0;
        sort(candidates.begin(),candidates.end());
        recursive(Pos,candidates,Length,target,item,result);
        return result;
    }
};

原方法:回溯+set判断集合唯一

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int>item;
        vector<vector<int>>result;
        set<vector<int>>only_set;
        int sum=0;//累加和
        int index=0;//从candidates[0]开始
        sort(candidates.begin(),candidates.end(),[&](int val1,int val2){
            //升序排序
            return val1<val2;
        });
        recursive(0,candidates,item,result,only_set,sum,target);
        return result;
    }
    void recursive(int i,vector<int>& nums,vector<int>& item,vector<vector<int>>& result,set<vector<int>>& only_set,int sum,int target){
        if(i>=nums.size()||sum>target)
            return;
        
        item.push_back(nums[i]);
        sum+=nums[i];
        //只有和==target并且set中唯一才能push到结果集
        if(sum==target&&only_set.find(item)==only_set.end()){
            result.push_back(item);
            only_set.insert(item);
        }
        recursive(i+1,nums,item,result,only_set,sum,target);
        //回溯,没得这个元素
        sum-=nums[i];//和-val
        item.pop_back();//弹出元素
        
        recursive(i+1,nums,item,result,only_set,sum,target);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值