Backtracking(回溯) 系列一combination

本文探讨了使用回溯法解决一系列组合问题的通用策略,包括组合、组合总和、组合总和II和组合总和III。通过详细的代码示例和解释,读者将了解如何在面对具有特定目标和限制条件的问题时,运用递归和回溯技巧来寻找所有可能的解决方案。

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

Tips:
这类题的共同点都是用backtracking,建立一个helper API然后recursion

  • input candidates needs sort,一是为了方便判断sum target提前退出(减枝),二是为了方便remove duplicates
    sort(candidates.begin(), candidates.end())

helper API有几个共同点:

  • input:res,row,start
  • exit condition:
    1,如果return有array size要求,比如combinations,要求k=2,exit condition就是:row.size()==k
    2,如果return是target,比如combinations sum I and II, 要求target,exit condition就是:
    target == 0
    并且可以提前return,
    if(candidates[i] > target) return;
    比如all combination sum。
    3,如果return既有target,又有size要求,比如combination sum III,exit condition就是:
    row.size()==k && target == 0
  • start 在recursion时的选择
    如果元素不能重复利用,recursion helper时start就是i + 1. (combination,combination sum II,combination sum III)
    反之就是i (combination sum I)
  • 如果input candidates有重复元素,需要remove duplicates,
    while(i+1 < candidates.size() && candidates[i] == candidates[i+1]) i++;
    比如combination II。

Leetcode:
77. Combinations

Input: n = 4, k = 2
Output:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>>res;
        if(n < k) return res;
        vector<int>row;
        combineHelper(res, row, n, k, 1);
        return res;
    }
    
private:
    void combineHelper(vector<vector<int>> & res, vector<int>&row, int n, int k, int start)
    {
        if(row.size() == k)
        {
            res.push_back(row);
            return;
        }
        
        for(int i = start; i <= n; i++)
        {
            row.push_back(i);
            combineHelper(res, row, n, k, i+1);
            row.pop_back();
        }
    }
}; 
};
  1. Combination Sum
    Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
    The same repeated number may be chosen from candidates unlimited number of times.
class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<vector<int>>res;
        vector<int>row;
        helper(res, row, candidates, target, 0);
        return res;
    }
    
    void helper(vector<vector<int>> &res, vector<int>& row, vector<int>& candidates, int target, int start)
    {
        if(target == 0)
        {
            res.push_back(row);
            return;
        }
        for(int i = start; i < candidates.size(); i++)
        {
            if(candidates[i] > target) return;
            row.push_back(candidates[i]);
            helper(res, row, candidates, target - candidates[i], i);
            row.pop_back();
        }
    }
};
  1. Combination Sum II
    Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
    Each number in candidates may only be used once in the combination.
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>>res;
        sort(candidates.begin(), candidates.end());
        vector<int>row;
        helper(candidates, res, row, target, 0);
        return res;
    }
    
    
    void helper(vector<int>& candidates, vector<vector<int>>&res, vector<int>row, int target, int start)
    {
        if(target == 0)
        {
            res.push_back(row);
            return;
        }
        for(int i = start; i < candidates.size(); i++)
        {
            if(candidates[i] > target)
            {
                return;
            }
            row.push_back(candidates[i]);
            helper(candidates, res, row, target - candidates[i], i + 1);
            row.pop_back();
            while(i+1 < candidates.size() && candidates[i] == candidates[i+1]) i++;
        }
    }
};
  1. Combination Sum III
    Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>>res;
        vector<int>row;
        helper(res, row, k, n, 1);
        return res;
    }
    
    void helper(vector<vector<int>>&res, vector<int>&row, int k, int target, int start)
    {
        if(row.size() == k && target == 0)
        {
            res.push_back(row);
            return;
        }
        
        for(int i = start; i <= 9; i++)
        {
            if(i > target) return;
            row.push_back(i);
            helper(res, row, k, target - i, i + 1);
            row.pop_back();
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值