「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」。
题目
链接:leetcode-cn.com/problems/co…
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
**输入:**n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
示例 2:
**输入:**n = 1, k = 1 输出:[[1]]
提示:
1 <= n <= 201 <= k <= n
解题思路
思路1
- 从起点开始遍历,若当前路径达到要求,拷贝一份,推入答案数组
- 否则,遍历起点到
n,将当前i加入路径 - 更新起点,继续遍历
- 记得遍历完,要将路径弹出一个元素
代码
const combine = (n, k) => {
// 最后的答案
const res = [];
// start是起点,path是路径的数组
const search = (start, path) => {
if (path.length === k) {
// 如果路径长度为k,满足题目要求了
// 将path推入答案res
res.push(path.slice());
return;
}
for (let i = start; i <= n; i++) {
// 每找一个,推入path一个
path.push(i);
// 从i+1,接着path继续找
search(i + 1, path);
// 上一级找完,path尾巴要拿出来
path.pop();
}
};
search(1, []);
return res;
};
思路2
标准的回溯问题,套用代码模版
result = [];
function backtrack (path, list) {
if (满足条件) {
result.push(path);
return
}
for () {
// 做选择(前序遍历)
backtrack (path, list)
// 撤销选择(后续遍历)
}
}
代码
var combine = function(n, k) {
if (k <= 0 || n <= 0) return res;
const ans = [];
const backtrack = (n, k, start, track) => {
if (k === track.length) {
ans.push(track)
return
}
for (let i = start; i <= n; i++) {
track.push(i)
backtrack(n, k, i + 1, [...track])
track.pop()
}
}
backtrack(n, k, 1, []);
return ans;
};
我们把这个过程当成一个树,这样可以考虑用DFS来解,就是求每条路径,代码如下:
var combine = function(n, k) {
const ans = [];
const dfs = (cur, n, k, temp) => {
// 剪枝:temp 长度加上区间 [cur, n] 的长度小于 k,不可能构造出长度为 k 的 temp
if (temp.length + (n - cur + 1) < k) {
return;
}
// 记录合法的答案
if (temp.length == k) {
ans.push(temp);
return;
}
// 考虑选择当前位置
dfs(cur + 1, n, k, [...temp, cur]);
// 考虑不选择当前位置
dfs(cur + 1, n, k, temp);
}
dfs(1, n, k, []);
return ans;
};
思路3
比如 1,2,3,4 取两个数,我们的思考是
- 先取一个1,得到 12 13 14
- 再取一个2,得到 23 24
- 再取一个3,得到 34
- 总结出一个规律,就是每次位移一个单位,从后边取 k-1个
代码
function pick(arr, start, num) {
let r = [];
if (num === 1) {
for (let a = start; a < arr.length; a++) {
r.push([arr[a]])
}
return r;
}
for (let i = start; i < arr.length; i++) {
let startValue = arr[i];
let rest = pick(arr, i + 1, num - 1);
for (let k = 0; k < rest.length; k++) {
r.push([startValue, ...rest[k]])
}
}
return r;
}
var combine = function (n, k) {
let nums = [];
for (let a = 1; a <= n; a++) {
nums.push(a)
}
return pick(nums, 0, k);
};