LeetCode 40: Combination Sum II

本文介绍了一个经典的算法问题——组合总和II,给定一组候选数字和目标数字,寻找所有不重复的组合使得数字之和等于目标值。文章详细阐述了解决方案的回溯法思路,包括对输入数组进行排序、跳过重复数字并统计重复次数等关键步骤。

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

Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1,a2,,ak) must be in non-descending order. (ie, a1a2ak).
  • The solution set must not contain duplicate combinations.

For example, given candidate set 10,1,2,7,6,1,5 and target 8,
A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]

解题思路

依然采用回溯法求解。 、

先对数组进行排序。

注意数组中的每个数 candidates[i] 不允许被使用多次,但如果一个数在数组中出现多次的话,就可以使用多次(比如 candidates[i]=candidates[j]=10,ij,则 10 可以使用 2 次)。

在递归之前,我们需要跳过重复的数字,并统计该数字重复的次数。

代码如下:

class Solution {
private:
    void internalCombinationSum2(vector<int> &candidates, int idx, int target, 
                                    vector<int> &path, vector<vector<int>> &res) {
        if ((target < 0) || (idx >= candidates.size() && target > 0)) return;

        if (target == 0) {
            // 找到了一个组合之和等于 target
            res.push_back(path);
            return;
        }

        // 统计每个数字可以重复的次数
        int repeate = 1;
        while ((idx < candidates.size() - 1) && (candidates[idx] == candidates[idx+1])) {
            repeate++;
            idx++; // Note
        }

        for (int r = 0; r <= repeate; ++r) {
            path.insert(path.end(), r, candidates[idx]);

            // 递归
            internalCombinationSum2(candidates, idx + 1, 
                    target - r * candidates[idx], path, res);

            path.erase(path.end() - r, path.end());
        }
    }

public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int> path;
        vector<vector<int>> result;

        sort(candidates.begin(), candidates.end()); // 排序
        internalCombinationSum2(candidates, 0, target, path, result);

        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值