代码随想录的第二十一天(回溯算法)

78 阅读1分钟

代码随想录的第二十一天(回溯算法)

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