组合总和问题,leetcode77,216,39,40

 leetcode77

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]
class Solution {
public:
    vector<vector<int>> res;//返回的答案
    vector<int> temp;//符合条件的某一路径

    vector<vector<int>> combine(int n, int k) {
        backtracking(n,k,1);
        return res;
    }
    void backtracking(int n, int k,int start){//start参数保证不重复选取
    if(temp.size()==k){
        res.push_back(temp);
        return;
    }
    for(int i=start;i<= n;i++){
        //在集合n中⾄多要从该起始位置 : n - (k - temp.size()) + 1,开始遍历
        temp.push_back(i);
        backtracking(n,k,i+1);//递归
        temp.pop_back();//回溯
    }
    }
};

leetcode 216

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

  • 所有数字都是正整数。
  • 解集不能包含重复的组合。

示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]

示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]

class Solution {
public:
    vector<vector<int>> res;
    vector<int> temp;
    int sum=0;
    vector<vector<int>> combinationSum3(int k, int n) {
        // res.clear(); // 可以不加
        // temp.clear();
        backtracking(k,n,1);
        return res;
    }

    void backtracking(int k, int n,int start){
        //if(sum>n) return;
        if(temp.size()==k){
            if(sum==n) res.push_back(temp);
            return;//个数等于k,但是sum不符合直接return
        }
        for(int i=start;i<=9;i++){
            temp.push_back(i);
            sum+=i;
            backtracking(k,n,i+1);//这里要是或者i+1,用++i,
            temp.pop_back();
            sum-=i;
        }
    }
};

 leetcode 39

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。
  • 示例输入:candidates = [2,3,6,7], target = 7,
  • 所求解集为: [ [7], [2,2,3] ]
class Solution {
public:
    vector<vector<int>>  res;
    vector<int> s;
    

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        backtracking(candidates,target,0,0);
        return res;
    }

    void backtracking(vector<int>& candidates,int target,int sum,int start){
        if(sum>target) return;
        if(sum==target){
            res.push_back(s);
            return;
        }

        for(int i=start;i<candidates.size();i++){//横向去重,纵向不去重
            sum+=candidates[i];
            s.push_back(candidates[i]);
            backtracking(candidates,target,sum,i);//这里不要加1了,表示当前数据可以重复加入
            sum-=candidates[i];
            s.pop_back();
            
        }
    }
};

leetcode 40

给定一个数组 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]
    ]
class Solution {
public:
    vector<vector<int>> res;
    vector<int> s;
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int> used(candidates.size(),0);
        sort(candidates.begin(),candidates.end());//先排序,让相同的元素挨在一起
        backtracking(candidates, target,0,0,used);
        return res;
    }
    void backtracking(vector<int>& candidates, int target,int start,int sum,vector<int> &used){
        
        if(sum>target) return;
        if(sum==target){
            res.push_back(s);
            return;
        }
        
        for(int i=start;i<candidates.size();i++){//开树枝是用for循环,不断向下延伸是递归
            //if(i > 0 && candidates[i] == candidates[i-1] && used[i-1] == 0) continue;
            if(i > 0 && candidates[i] == candidates[i-1] && i>start) continue;
            //不使用used数组也可以,if(i > 0 && candidates[i] == candidates[i-1] && i>start) continue;
            //注意这里是判断used[i-1]
            sum+=candidates[i];
            s.push_back(candidates[i]);
            //used[i]=1;
            backtracking(candidates,target,i+1,sum,used);
            sum-=candidates[i];
            s.pop_back();
            //used[i]=0;
        }

    }
};

猜你喜欢

转载自blog.csdn.net/hbzdsXCV/article/details/130832642
今日推荐