C++ 【回溯】如何在一组数中找到和为目标值的子集

组合数之和2

题目[leetcode40]

给定一个数组 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] ]

思路

依照回溯的思想,试探性的加上每个元素分以下情况:
①当所加入的元素总值sum 超过了目标值target时,进行回溯操作。(涉及剪枝操作:将已不满足的情况,不再进行深入的讨论)
②当所加入的元素总值sum 等于目标值target时,将该数组加入到二维数组中,保存该结果。
③当总值 小于目标值target时,继续进行下一个元素的加入。

这个过程中,依然要做到去重的操作,就用到了set数组集合进行判断该一维数组是否已存在结果中。
(上述操作就是在所有不重复的子集中,找到合适的情况,并保存)

形式如下:

代码实现如下:

#include <iostream>
#include <vector>
#include <set>

using namespace std;

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        vector<int> item;
        set<vector<int>> res_set;
        sort(candidates.begin(), candidates.end()); //排序,去除位置重复
        generate(0, candidates, result, item, res_set, 0, target);
        return result;
    }
private:
    void generate(int i, vector<int> &nums, vector<vector<int>> &result, vector<int> &item, set<vector<int>> &res_set, int sum, int target){
        if(i >= nums.size() || sum > target){ //递归结束条件,剪枝
            return;
        }
        sum += nums[i];
        item.push_back(nums[i]);
        if(sum == target && res_set.find(item) == res_set.end()){ //保证不重复后,存入结果
            result.push_back(item);
            res_set.insert(item);
        }
        generate(i+1, nums, result, item, res_set, sum, target);
        sum -= nums[i]; //回溯操作
        item.pop_back();
        generate(i+1, nums, result, item, res_set, sum, target);
    }
};

致谢

本章知识点和思路由小象学院相关视频提供,由本人学习并梳理得出,希望自己加深记忆的同时,也能给大家提供更多有关于一些算法的知识点。
你的点赞、评论、收藏就是对我最大的支持与鼓励,谢谢!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值