40. 组合总和 II

发布于:2025-05-10 ⋅ 阅读:(11) ⋅ 点赞:(0)

题目

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

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

注意:解集不能包含重复的组合。 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

提示:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

思路

        因为有可能出现重复组合或者数组中的数本身都比目标值要大,所以我们就要规避这种现象,我们可以先对数组中的数进行排序,如果有数字大于目标值那么这个数一定不能在组合里面,这个数字后面的数也一定不能,就可以省去一些搜索步骤。在遍历中,从start开始可以避免重复,如果前一个数和自己相等就跳过,防止产生重复组合,经过筛选,符合条件的数就先存在临时数组p中,如果从下一轮回溯又返回到当前,那么就把这个数弹出,用其他数继续试。

代码

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int> p;//存组合中的数字           
        sort(candidates.begin(), candidates.end());//排序,方便判断数字是否能作为组合中符合条件的数字
        int start=0;//从0开始遍历
        vector<vector<int>> res;//结果数组
        hs(p, target, candidates, start, res);
        return res;
    }
    void hs(vector<int>& p,int target,vector<int> &c,int start,vector<vector<int>> &res)
    {
        if(target==0)//代表找到了符合条件的组合
        {
            res.push_back(p);
            return;
        }
        for(int i=start;i<c.size();i++)//避免生成重复组合
        {
            if(target-c[i]<0)//因为数组是经过排序的,当前数字比目标值还要大,剩下的也都不用在判断了
            {
                break;
            }
            if(i>start&&c[i]==c[i-1])//前一个数和当前数相等,会导致重复,跳过
            {
                continue;
            }
            p.push_back(c[i]);//数字符合条件,先存入
            hs(p,target-c[i],c,i+1,res);//下一轮
            p.pop_back();//回溯,恢复之前状态,生成更多选择
        }
    }
};


网站公告

今日签到

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