LeetCode刷题之组合总和

  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:
    熟记回溯算法的大致框架,在回溯时一定要对保存当前数组进行弹出,还要对已经组成的和进行减法运算。

Guess you like

Origin blog.csdn.net/qq_43964318/article/details/121388487