题目描述:给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例: 输入: n = 4, k = 2 输出: [
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
在深度优先搜索中,有时我们会去掉一些不符合题目要求的、没作用的答案,进而得到正确答案。这个丢掉答案的过程,形似减掉树的枝叶,所以这一方法被称为“剪枝”。
在这道题中,要做到剪枝,我们需要分别在组合问题的递归式和递归边界上动手脚:
- 递归式:普通组合问题,每到一个新的坑位处,我们都需要对组合结果数组进行更新;这道题中,当且仅当组合内数字个数为
k
个时,才会对组合结果数组进行更新。 - 递归边界:只要组合内数字个数达到了
k
个,就不再继续当前的路径往下遍历,而是直接返回。
/**
* @param {number} n
* @param {number} k
* @return {number[][]}
*/
const combine = function(n, k) {
// 初始化结果数组
const res = []
// 初始化组合数组
const subset = []
// 进入 dfs,起始数字是1
dfs(1)
// 定义 dfs 函数,入参是当前遍历到的数字
function dfs(index) {
if(subset.length === k) {
res.push(subset.slice())
return
}
// 从当前数字的值开始,遍历 index-n 之间的所有数字
for(let i=index;i<=n;i++) {
// 这是当前数字存在于组合中的情况
subset.push(i)
// 基于当前数字存在于组合中的情况,进一步 dfs
dfs(i+1)
// 这是当前数字不存在与组合中的情况
subset.pop()
}
}
// 返回结果数组
return res
};