代码随想录的第二十一天(回溯算法)
77. 组合
var combine = function(n, k) {
let result = []
let path = []
function backtracking(n, k, startIndex) {
if (path.length === k) {
result.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 result
};
思路:
1、首先定义两个参数,一个是用来存放最终结果的;还有一个是用来存放,当前集合的
2、当当前集合等于目标长度K的时候,说明符合条件需要存入result中;这儿为啥要return?因为要接着走后面的逻辑,就是回溯的那部分,当符合条件后,需要将当前数组最后一个值抛出去,然后换下一个
3、回溯的过程:就是存入当前值到集合中,然后进行递归,符合条件存入result中,不符合就抛出走下一个
单层递归需要明白的一点儿是:只有第一次是走的for循环,后面循环除非走完,否则都是走的递归中的循环
还有就是startIndex是根据每层去进行集合,下一层是从2开始
简单理解:可以先把递归去掉,第一层就是push(i)然后等于k的时候存入数组,然后pop出去,然后再次存入;递归就是从第二次再次开始
剪枝操作:
for (let i = startIndex; i <= n; i++) =》 for (let i = startIndex; i <= n - (k - path.length) + 1; i++)
path.length:已经找到的个数
k - path.length:还需找的个数
数组长度起码是k - path.length才有意义,所以i至多是等于n - (k - path.length) + 1