理论基础
其实在讲解二叉树的时候,就给大家介绍过回溯,这次正式开启回溯算法,大家可以先看视频,对回溯算法有一个整体的了解。
题目链接/文章讲解:https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
视频讲解:https://www.bilibili.com/video/BV1cy4y167mM
回溯模板
void backtracking() {
if(停止条件) {
收集结果;
return;
}
for(集合元素) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯操作;
}
return;
}
77. 组合
对着 在 回溯算法理论基础 给出的 代码模板,来做本题组合问题,大家就会发现 写回溯算法套路。
在回溯算法解决实际问题的过程中,大家会有各种疑问,先看视频介绍,基本可以解决大家的疑惑。
本题关于剪枝操作是大家要理解的重点,因为后面很多回溯算法解决的题目,都是这个剪枝套路。
题目
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
思路
在用js解题的时候,要考虑深拷贝浅拷贝的问题。
答案
/**
* @param {number} n
* @param {number} k
* @return {number[][]}
*/
var combine = function(n, k) {
const res = []; // 结果
const path = []; // 存放符合条件的结果
const backtracking = function(n, k, startIndex) {
if(path.length === k) {
// 这里如果用 res.push(path),会得到空数组,所以要用展开符,深拷贝。
res.push([...path]);
return;
}
for(let i = startIndex; i <= n; i++) {
path.push(i);
backtracking(n, k, i+1);
path.pop();
}
}
backtracking(n, k, 1);
return res;
};