ii 组合总和_leetcode C++题解系列-039 组合总和II

32ac5580f074acdf28c49039e5e59c3a.png

题目

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

解题代码与测试

 Created by tannzh on 2020/7/4.///* * 组合总和 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]] */#include #include using std::vector;class Solution {public:    vector> combinationSum2(vector& candidates, int target) {        vector> ret;        std::sort(candidates.begin(), candidates.end());        dfs(candidates, ret, target, vector{}, 0);        return ret;    }private:    void dfs(const vector &num, vector> &ret, int target, vector cur, size_t start) {        if (target == 0) { ret.push_back(cur); return; }        for (auto i = start; i < num.size(); ++i)            if (i > start && num[i] == num[i-1]) continue;            else if (num.at(i) <= target) {                cur.push_back(num.at(i));                dfs(num, ret, target - num.at(i), cur, i+1);                cur.pop_back();            } else break;    }};int main(int argc, char **argv){    Solution s;    std::vector vec{10,1,2,7,6,1,5};    for (const auto &v : s.combinationSum2(vec, 8)) {        for (auto i : v)            std::cout << i << " ";        std::cout << std::endl;    }    return 0;}

解题思路分析

这题的主要思路参考上一篇, 大同小异,涉及的思想,依旧是 DFS。

要额外注意的有两点:

  1. Each number in C may only be used once in the combination.
  2. The solution set must not contain duplicate combinations.

对于第一点,我们可以在递归中,给下一个 start 传参为 i+1 来解决。

对于第二点,有两种思路:

  1. 使用 std::set> 来存储返回值,缺点是效率较低。
  2. 在递归函数中增加条件:if (i > start && num[i] == num[i-1]) continue; 无比轻巧的避过了重复项。

我当然选择了第二种,效率遥遥领先呢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值