【Leetcode】77. 组合

93 阅读1分钟

leetcode-77.png

题目简述:1-n 个数字里面, 选出 k 个来,元素不能重复使用,列出所有的情况,也就是C(n,k)种情况
216题,也没啥不同就是

思路解析

我们可以使用回溯算法来解决这个问题。回溯的核心就是“选择 + 递归 + 撤销选择”,这在组合类问题中是一种非常常见且高效的模式。

image.png

关键点有两个:

  1. for 循环中的 start 参数是剪枝的关键之一
    我们只从当前数字往后枚举,避免重复和无效搜索。
  2. 每次递归中都判断长度是否为 k,如果是,就将当前组合加入结果中。
var combine = function (n, k) {
    // n 个数字选 k 个
    let res = []
    var backtrack = function (start, one) {
        if (one.length === k) {
            res.push([...one])
            return
        }
        for (let i = start; i <= n; ++i) {
            one.push(i)
            backtrack(i + 1, one)
            one.pop()
        }
    }
    backtrack(1, [])
    return res
};

关于剪枝优化

我们这里的剪枝操作体现在两个地方:

  • 起始位置 start 控制了数字不能重复使用且避免重复组合(比如 [1,2] 和 [2,1] 是同一个组合,应该只出现一次)。
  • 若想更进一步地优化,还可以添加如下剪枝判断,减少递归层数:
for (let i = start; i <= n - (k - one.length) + 1; ++i)

这个优化确保了在剩余数字不足以组成 k 个数时就不再递归,节省不必要的搜索。


小结

  • 回溯模板在组合类题目中非常通用。
  • 灵活控制 start 参数和使用 path.pop() 回退,是解决该题的关键。
  • 216题,和这题比较像,只需要去掉一些和“求和”相关的逻辑即可。