40LeetCode刷题之组合总和2(回溯法)

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题思路:
看到这种需要不断组合来进行解决的题目,最直接的思路就是使用DFS,通俗来讲就是使用回溯算法,这和之前的题目是类似的。
重点就是回溯算法该怎么写。
这里我给出了两种解法。
3. 解题代码:
第一种解法:这种是直接对target进行减法的运算,直到target = 0结束。

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        int length = candidates.size();
        //先对vector进行排序
        sort(candidates.begin(),candidates.end());
        vector<vector<int>> res;
        vector<int> current;
        if(length == 0){
            return {};
        }
        if(candidates[0] > target){
            return {};
        }
        DFS(res,candidates,target,current,0);
        return res;
    }
    void DFS(vector<vector<int>> &res,vector<int> candidates,int target,vector<int> &current,int deep){
        //终止条件
        if(target == 0){
            res.push_back(current);
            return;
        }
        for(int i = deep; i < candidates.size() && target > 0;i++){
            //对同一树层使用过的数组进行去重
            if(i > deep && candidates[i] == candidates[i-1]){
                continue;
            }
            target = target - candidates[i];
            current.push_back(candidates[i]);
            DFS(res,candidates,target,current,i+1);
            target += candidates[i];
            current.pop_back();
        }
    }
};

第二种解法:这种解法是每次对sum进行加法运算,直到sum = target 结束。

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        int length = candidates.size();
        //先对vector进行排序
        sort(candidates.begin(),candidates.end());
        vector<vector<int>> res;
        vector<int> current;
        if(length == 0){
            return {};
        }
        if(candidates[0] > target){
            return {};
        }
        DFS(res,candidates,target,current,0,0);
        return res;
    }
    void DFS(vector<vector<int>> &res,vector<int> candidates,int target,vector<int> &current,int deep,int sum){
        //终止条件(对结果进行收集)
        if(target == sum){
            res.push_back(current);
            return;
        }
        // 每次搜索的宽度
        for(int i = deep; i < candidates.size() && sum + candidates[i] <= target ;i++){

            //处理结点
            //对同一树层使用过的数组进行去重
            if(i > deep && candidates[i] == candidates[i-1]){
                continue;
            }
            sum = sum + candidates[i];
            current.push_back(candidates[i]);
            //递归
            DFS(res,candidates,target,current,i+1,sum);
            //回溯
            sum -= candidates[i];
            current.pop_back();
        }
    }
};
  1. tips:
    熟记回溯算法的大致框架,在回溯时一定要对保存当前数组进行弹出,还要对已经组成的和进行减法运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

强大的RGG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值