zlatan的算法笔记3--回溯的组合总和问题III(力扣216题)

算法笔记3

通过之前题目的我们对于使用回溯法解决组合问题已经有了一个大致的方向,本题同样是一道组合总和问题,结合前两题的思路,未剪枝的代码是可以有思路写出来的。

题目描述

在这里插入图片描述初看题目就很容易发现本题像是之前做过的两道题的综合,既可以看到相加之和n,也看到了记录数字个数的k,那么就可以通过三部曲来解题了。

解题过程

1.选择参数:在参数选择上,除了题目中给定的表示组合总和的n与表示每条路径有几个数字的k,还需要规定初始位置的参数startIndex,记录路径的一维数组path与记录结果的二维数组result,至此参数选择完毕。

2.确定终止条件:在第一天的组合问题中,我们知道path用来记录每个组合的路径,path的大小就等于每条路径有几个数字,所以第一个条件就是当path的大小等于k,这时就可以记录结果,除了这个条件我们还要满足加和的条件,即sum是否等于目标值n,满足以上两个条件就可以用result数组收集最终结果为了代码的健壮性,我们也可以提前判断sum大于n的情况直接跳出就好了。

        if(sum >= n) {
            return;
        }
        if(path.size() == k && sum == n) {
            result.push_back(path);
            return;
        }

3.循环递归回溯:for循环里面我们需要考虑的是判断条件,题目中说数字只在1-9之间去取,所以直接简单设置为i <= 9或者i < 10即可。下面就是与算法笔记2一样常规的收集路径,加和每一项的值,进行递归操作,题目中没有说每个数字可以重复使用,所以我们的第三个参数设置为i + 1。最后就是回溯操作,之前怎么操作就怎么回退就好了,先拿sum减去之前加的内容以及path吐出之前的元素。

        for(int i = startIndex; i <= 9; i++) {
            path.push_back(i);
            sum += i;
            backtracking(k, n, i + 1);
            sum -= i;
            path.pop_back();
        }
    }

完整代码

class Solution {
public:

    vector<int> path;
    vector<vector<int>> result;
    int sum;

    void backtracking(int k, int n, int startIndex) {
        if(sum >= n) {
            return;
        }
        if(path.size() == k && sum == n) {
            result.push_back(path);
            return;
        }

        for(int i = startIndex; i <= 9; i++) {
            path.push_back(i);
            sum += i;
            backtracking(k, n, i + 1);
            sum -= i;
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(k, n, 1);
        return result;
    }
};

剪枝优化

这里优化思想可以完全参考1.1的做法,即n - (k - path.size()) + 1,参考下来仿写一下就可以了,即i <= 9 - (k - path.size()) + 1。

class Solution {
public:

    vector<int> path;
    vector<vector<int>> result;
    int sum;

    void backtracking(int k, int n, int startIndex) {
        if(sum >= n) {
            return;
        }
        if(path.size() == k && sum == n) {
            result.push_back(path);
            return;
        }

        for(int i = startIndex; i <= 9 - (k - path.size()) - 1; i++) {
            path.push_back(i);
            sum += i;
            backtracking(k, n, i + 1);
            sum -= i;
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(k, n, 1);
        return result;
    }
};


结语

今天的题目比较轻松,算是作为之前几次内容的复习巩固。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值