JS回溯算法思路总结(leetcode)

1、定义

回溯算法:回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

解决一个回溯问题,实际上就是一个决策树的遍历过程。

2、模板

三个步骤:

(1)开头写好跳出条件,满足条件才将当前结果加入总结果中。

(2)已经拿过的数不再拿。

(3)向下遍历,结束后回溯到上一步。

伪代码:

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:                  // (1)
        result.add(路径)
        return
​
    for 选择 in 选择列表:
        去掉已经拿过的数              // (2)
        做选择                       // (3)
        backtrack(路径, 选择列表)     
        撤销选择

3、leetcode真题(全排列、子集、组合、拓展题)

  • 全排列问题(leetcode46)

var allArray = function(nums) {
    var res = []
    var dfs = function(path){
        if(nums.length === path.length){              //(1)
            res.push([...path]);
            return;
        }
        for(let i=0; i<nums.length; i++){
            if(path.indexOf(nums[i]) !== -1) {        //(2)
                continue;
            }
            path.push(nums[i]);                       //(3)
            dfs(path);
            path.pop();

        }
    }
    dfs([]);
    return res;
};

console.log(allArray([1,2,3]))          
// [[ 1, 2, 3 ],[ 1, 3, 2 ],[ 2, 1, 3 ],[ 2, 3, 1 ],[ 3, 1, 2 ],[ 3, 2, 1 ]]
  • 子集问题(leetcode78)

和全排列区别:

1》所有可能的子集,每次递归中都将当前组合加入结果中,不用之前的结束条件。

2》[1,3]和[3,1]是相同的,故每次取数时要从其位置取后面的数,加个标志位start。

var sonArray = function(nums) {
    var res = [];
    var dfs = function(path,start) {
        res.push([...path])                        //(1)
        for(let i=start; i<nums.length; i++) {     //(2)
            path.push(nums[i]);                    //(3)
            dfs(path,i+1);
            path.pop();
        }
    }
    dfs([],0)
    return res;
}

console.log(sonArray([1,2,3]))
//[ [], [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 1, 3 ], [ 2 ], [ 2, 3 ], [ 3 ] ]
  • 组合求和问题(leetcode39)

和全排列区别:

1》结束条件是满足目标target。

2》组合包括自身和,故每次取数时要从自己位置开始取数。

var targetArray = function(nums, target) {
    var res = [];
    var dfs = function(path,start) {
        if(sum(path) === target) {                  //(1)
            res.push([...path]);
            return;
        }
        if(sum(path) > target) {
            return;
        }
        for(let i=start; i<nums.length; i++) {     //(2)
            path.push(nums[i]);                    //(3)
            dfs(path.slice(), i);
            path.pop();
        }
    }
    dfs([],0)
    return res;
}
function sum(arr) {
    if(arr.length===0)
        return 0;
    return arr.reduce((a,b)=>a+b)
}

console.log(targetArray([2,3,5],8))
// [ [ 2, 2, 2, 2 ], [ 2, 3, 3 ], [ 3, 5 ] ]
  • 拓展题

输入目标字符串:比如”南京“输出包含目标字符串的节点路径集合。


function func(arr, str) {
    var res = [];
    var recur = function(arr, path) {
        let string = path.join('-');
        if(string.indexOf(str) !== -1){
            res.push(string);
        }
        if(arr === undefined || arr.length === 0)
            return;
        
        for(let i=0; i<arr.length; i++){
            path.push(arr[i].label);
            recur(arr[i].children, path);
            path.pop();
        }
    }
    recur(arr, []);
    return res;
}

console.log(func([{label:'江苏省',children:[{label:'南京市',children:[{label:'xxx区',children:[]}]}]}],'南京'))
//[ '江苏省-南京市', '江苏省-南京市-xxx区' ]

 

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值