【LeetCode】216. 组合总和 III(中等)——代码随想录算法训练营Day25

题目链接:216. 组合总和 III

题目描述

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次 

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:

输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:

输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:

输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

提示:

  • 2 <= k <= 9
  • 1 <= n <= 60

文章讲解:代码随想录

视频讲解:和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III_哔哩哔哩_bilibili

题解1:回溯法

思路:使用回溯法来求解组合问题。

回溯分析:

  • 递归函数的参数和返回值:首先创建3个变量 res、path 和 sum,path 记录遍历的路径,sum 记录当前路径和,res 记录结果。递归函数的返回值为 void,参数是 n 和 k,还有一个 start 来记录本次递归的开始位置。
  • 递归函数的终止条件:找到叶子节点,即 path 的长度和 k 相同,且路径和等于目标值,也就是找到了一个符合题目要求的组合,将这个组合存入结果数组。
  • 单层递归的逻辑:使用 for 循环从开始位置 start 开始直到 n 横向遍历,递归的向下纵向遍历寻找组合。
  • 剪枝:path 的长度为已选择的元素数,如果剩余的元素数小于 k - path.length,即这条路径找不到符合要求的组合了,就可以做剪枝;当路径和比目标值大时,也应该做剪枝。
/**
 * @param {number} k
 * @param {number} n
 * @return {number[][]}
 */
var combinationSum3 = function(k, n) {
    if (n > k * (9 - (k - 1) + 9) / 2 || n < k * (1 + (1 + (k - 1))) / 2) {
        return []; // 若无符合条件的结果,直接返回空
    }
    const res = []; // 结果数组
    const path = []; // 路径
    let sum = 0; // 当前路径和
    // 回溯函数
    const backtracking = function (k, n, start) {
        if (path.length > k) {
            return; // 路径长度超过 k,直接返回
        }
        if (path.length === k) {
            // 路径长度为 k,符合要求则加入结果数组,然后返回
            sum === n && res.push([...path]);
            return;
        }
        for (let i = start; i <= 9 - (k - path.length) + 1; i++) { // 剪枝
            if (sum + i > n) {
                return; // 剪枝,如果路径和超过目标值,则再往下也找不出结果了,直接返回
            }
            // 记录路径
            path.push(i);
            sum += i;
            backtracking(k, n, i + 1); // 继续向下查找
            // 回溯
            path.pop();
            sum -= i;
        }
    }
    backtracking(k, n, 1);
    return res;
};

分析:时间复杂度为 O(n * 2 ^ n),空间复杂度为 O(n)。

收获

练习使用回溯法解决组合问题,根据题目内容在合适的代码位置做剪枝操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴雪月乔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值