C++算法学习心得六.回溯算法(2)

1.组合总和(39题)

题目描述:

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

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

说明:

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

示例 1:

  • 输入:candidates = [2,3,6,7], target = 7,
  • 所求解集为: [ [7], [2,2,3] ]

回溯法: 如果是一个集合来求组合的话,就需要startIndex,如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,只是组合情况,与之前组合问题不一致的是该题可以重复选择,主要在于递归函数的startindex选取,

class Solution {
private: 
    vector<int>path;//路径
    vector<vector<int>>result;//结果集
    //回溯函数,需要参数:数组,目标,和,组合问题需要startindex来解决
    void backtracking(vector<int>& candidates,int target,int sum,int startindex){
        if(sum > target){
            return ;//如果和大于目标值直接返回
        }
        if(sum == target){
            result.push_back(path);//和和目标值相等,将路径加入结果集中
            return ;
        }
        //组合数组的遍历,遍历的集合树的宽度
        for(int i = startindex;i < candidates.size();i++){
            sum += candidates[i];//和求法
            path.push_back(candidates[i]);//路径加入
            backtracking(candidates,target,sum,i);//递归
            path.pop_back();//回溯
            sum -= candidates[i];//回溯
        }
    }
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        backtracking(candidates,target,0,0);
        return result;
    }
};

减枝操作:对总集合排序之后,如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历

class Solution {
private: 
    vector<int>path;//路径
    vector<vector<int>>result;//结果集
    //回溯函数,需要参数:数组,目标,和,组合问题需要startindex来解决
    void backtracking(vector<int>& candidates,int target,int sum,int startindex){
        if(sum > target){
            return ;//如果和大于目标值直接返回
        }
        if(sum == target){
            result.push_back(path);//和和目标值相等,将路径加入结果集中
            return ;
        }
        //组合数组的遍历,遍历的集合树的宽度,排序进行,如果sum+该值大于了目标值就不进行操作实现减枝
        for(int i = startindex;i < candidates.size() && sum + candidates[i] <= target;i++){
            sum += candidates[i];//和求法
            path.push_back(candidates[i]);//路径加入
            backtracking(candidates,target,sum,i);//递归
            path.pop_back();//回溯
            sum -= candidates[i];//回溯
        }
    }
public:
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值