首页 > 编程语言 >Js回溯算法

Js回溯算法

时间:2022-10-17 11:33:29浏览次数:77  
标签:nums res length Js 算法 let 回溯 path

原文链接:https://www.cnblogs.com/yalong/p/16798569.html

回溯算法

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

什么问题适合用回溯算法

  • 有很多路
  • 路里面有死路, 也有出路
  • 通常需要用递归来模拟所有的路

今天我们就用这个 "通用解题方法" 来解决leetcode 上几个常见的题目

全排列

leetcode题目地址

解题思路:

用递归模拟全部的路,直到path 长度等于 nums 长度,这就到了死路,就可以结束递归

代码如下:

var permute = function(nums) {
     let res = []
     let fn = (path) => {
         if(path.length === nums.length) {
             res.push(path)
             return
         }
         nums.forEach(item => {
             if (!path.includes(item)) {
                 fn(path.concat(item))
             }
             
         })
     }
     fn([])
     return res
};

子集

leetcode题目地址

解题思路

跟上面的全排列类似,不过不能包含重复的子集,比如 123 跟 321 其实是相同的子集
那么我们在查找的时候,只要按照下标 index 从小到大查找,就可以避免321 这种排列的子集了
由于要找到全部子集,所以子集的长度可以是0-nums.length 之前的任意长度 n
递归函数结束的条件 就是 path 的长度 等于 n

代码

var subsets = function(nums) {
    const res = [];
    const backtrack = (path, l, start) => {
        if (path.length === l) {
            res.push(path)
            return;
        }
        for(let i=start; i<nums.length; i++) {
            backtrack(path.concat(nums[i]), l, i + 1)
        }
    }
    for (let i = 0; i <= nums.length; i++) {
        backtrack([], i, 0)
    }
    return res;
}

递增子序列

leetcode题目地址

解题思路

跟上面的 【子集】相似,不过在递归之前需要判断下,path中新加入的数必须大于等于 path 中最后一位数
比如数组 [1,2,3,3] 查找出来的结果包中有 123 123 这俩3 是不同位置的,但是输出的结果 只能有一个 123 就行了, 所以我们需要对结果进行一个去重处理

代码

var findSubsequences = function(nums) {
    const res = [];
    let obj = {}
    const backtrack = (path, l, start) => {
        if (path.length === l) {
            if (path.length > 1) { // 这里是去重
                let subStr = path.join(',')
                if (!obj[subStr]) {
                    obj[subStr] = true
                    res.push(path)
                }
            }
            return;
        }
        for(let i=start; i<nums.length; i++) {
            // 在加入数组之前 做个判断 如果数组有长度的话, 数组最后一位必须小于等于 num[i]
            if ((path.length && path[path.length - 1] <= nums[i]) || !path.length) {
                backtrack(path.concat(nums[i]), l, i + 1)
            }
        }
    }
    for (let i = 0; i <= nums.length; i++) {
        backtrack([], i, 0)
    }
    return res;
};

总结

凡是这种有很多路,并且有出路 也有死路的题目,都可以用回溯算法进行处理
记得递归函数一定要有结束条件,不然就陷入死循环了

标签:nums,res,length,Js,算法,let,回溯,path
From: https://www.cnblogs.com/yalong/p/16798569.html

相关文章

  • go json.Marshal 和 json.Unmarshal与结构体
    结构体属性名字小写会被忽略packagemainimport("encoding/json""fmt")typePeoplestruct{namestring`json:"name"`Heightstring`jso......
  • C/C++数据结构算法动态演示系统
    C/C++数据结构算法动态演示系统《数据结构与算法基础》课程项目课程项目题目:数据结构算法动态演示系统设计要求:设计并建立一套数据结构算法的动态演示系统。利用可......
  • web前端常用的js封装,收藏起来备用!
    做前端开发的同学是不是经常封装一些常用的函数方法,比如,日期格式、对象转换等。话不多说,直接总结一些常用的封装函数直接放在utils中拿来即用!//数组对象深拷贝constdeep......
  • nodejs base64 编码解码
    一、普通字符串编码varb=newBuffer('JavaScript');vars=b.toString('base64');//SmF2YVNjcmlwdA==解码:varb=newBuffer('SmF2YVNjcmlwdA==','base64')......
  • 基于雪花算法的增强版ID生成器
    sequence基于雪花算法的增强版ID生成器解决了时间回拨的问题无需手动指定workId,微服务环境自适应可配置化快速开始依赖引入<dependency><groupId>io.githu......
  • Node.js躬行记(24)——低代码
    低代码开发平台(LCDP)是无需编码(0代码)或通过少量代码就可以快速生成应用程序的开发平台。让具有不同经验水平的开发人员可以通过图形化的用户界面,通过拖拽组件和模型驱动......
  • Vue.js -- 样式绑定
    前言本文主要介绍了vue.js样式绑定的几种形式。class字符串形式代码演示:<!DOCTYPEhtml><htmllang="en"><head><title>vue样式绑定</title><scriptsrc=......
  • js列表合并以及处理响应数据
    JS实现列表元素合并 Vue做一个穿梭框的功能,需要用到合并列表元素,左列表合并到右列表。核心思路是右三个数据列表,左、右、选中method:{toRight:function(){......
  • AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。
    查表算法,无疑也是一种非常常用、有效而且快捷的算法,我们在很多算法的加速过程中都能看到他的影子,在图像处理中,尤其常用,但是查表在SSE指令的基础上很难得......
  • AVX图像算法优化系列一: 初步接触AVX。
    弄了SSE指令集,必然会在不同的场合不同的人群中了解到还有更为高级的AVX指令集的存在,早些年也确实有偶尔写点AVX的函数,但是一直没有深入的去了解,这个十一,......