回溯算法理论基础
文档讲解:代码随想录/回溯算法理论基础
视频讲解:视频讲解-回溯算法理论基础
状态:已完成(1遍)
总结
回溯法,一般可以解决如下几种问题:
- 组合问题:N个数里面按一定规则找出k个数的集合
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 棋盘问题:N皇后,解数独等等
回溯法解决的问题都可以抽象为树形结构。
因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。
递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。
相比于删除某个节点来说,节点若不符合区间的话处理起来方便很多。
77.组合
题目链接:77.组合
文档讲解:代码随想录/组合
视频讲解:视频讲解-组合
状态:已完成(1遍)
解题过程
看到题目的第一想法
我的想法是每次找到遍历一个数,再往后找第二个数,找到数组最后一个数结束;回溯到第一步再找第二个数,直到最后。但是没接触过回溯算法,我写不出来。。
看完代码随想录之后的想法
讲解之后对回溯三部曲有了更深刻的理解:返回值和参数,确定终止条件,遍历过程。
看了讲解手搓代码如下:
/**
* @param {number} n
* @param {number} k
* @return {number[][]}
*/
var combine = function(n, k) {
let ans = [],arr = [];
const huisu = function(startIndex){
if(arr.length == k){
ans.push(arr.slice());
return;
}
for(let i = startIndex;i<=n;i++){
arr.push(i);
huisu(i+1);
arr.pop();
}
}
huisu(1);
return ans;
};
提交没有问题。
文字讲解代码如下:
/**
* @param {number} n
* @param {number} k
* @return {number[][]}
*/
let result = []
let path = []
var combine = function (n, k) {
result = []
combineHelper(n, k, 1)
return result
};
const combineHelper = (n, k, startIndex) => {
if (path.length === k) {
result.push([...path])
return
}
for (let i = startIndex; i <= n - (k - path.length) + 1; ++i) {
path.push(i)
combineHelper(n, k, i + 1)
path.pop()
}
}
总结
这道题是经典的回溯三部曲,可以细细回品一下。