算法 --- 回溯法

回溯法

参考 - 剑指Offer

回溯法可以看成蛮力法的升级版,它从解决问题每一步的所有可能选项里系统地选择出一个可行的解决方案.

回溯法解决的问题的特性:

  • 可以形象地用树状结构表示:

    • 节点: 算法中的每一个步骤
    • 节点之间的连接线: 每个步骤中的选项,通过每一天连接线,可以到达下一个子步骤
    • 叶子节点: 代表一个步骤的最终状态
  • 如果在叶节点的状态满足需求,那么我们找到了一个可行的解决方案

  • 如果在叶节点的状态不满足约束条件,那么只好回溯到它的上一个节点再尝试其他的选项。如果上一个节点所有可能的选项都已经试过,并且不能达到满足约束条件的终结状态,则再次回溯到上一个节点.如果所有节点的所有选项都已经尝试过仍然不能达到满足约束条件的终结状态,该问题无解

栗子 - 数组总和

题目参考 - 39.数组总和

算法思路:

  • 变量:
    • 使用len缓存当前数组的长度
    • 使用path缓存当前的路径
    • 使用res缓存要返回的结果
  • 处理:
    • 为了方便后续的剪枝操作,需先对数组进行排序
  • 使用深度优先算法,传入3个参数: resides(离目标还差多少), path, begin(从哪一个开始添加)
    • 每次进入时,判断一下,resides是否小于0:
      • 是: return
      • 否: 不做处理
    • 之后判断resides是否等于0
      • 是: 证明找到一个条符合要求的路径,将path推入res中(此处需特别注意,数组是JS中的引用类型.在后文中会回溯,最终的path是一个空数组. 如果直接将path推入res.其实是将path的内存地址推入res.最终会根据地址寻找到空数组.因此此处推入的是path.slice()). slice方法参考
      • 否: 不做处理
    • 到这里,循环遍历candidates数组
      • 每次将当前的值推入路径
      • 然后调用dfs函数
      • dfs函数结束之后,要进行回溯操作,即将对path使用pop()方法
var combinationSum = function(candidates, target){let len = candidates.length,path = [],res = []candidates.sort((a,b)=>a-b)function dfs(resides, path, begin){if(resides < 0) returnif(resides == 0) return res.push(path.slice())	// 此处需要返回一个新的数组,不能使用同一个内存中的数组for(let i = begin; i < len ; i++){if(resides - candidates[i] < 0) break;path.push(candidates[i])dfs(resides - candidates[i], path, i)path.pop()}}dfs(target, path, 0)return res       
}

注意: res.push(path)时,由于path是个引用类型.因此实际上push进的是一个十六进制地址.可以看做下面:

res[0] = ‘0xffffffff’

当后面回溯path.pop()时, 内存0xffffffff中的值会改变.

最后一次回溯 内存0xffffffff中的值为 []

因此 res[0] = []

而我们需要得到的是res[0] = [a,b,c] 这样的结构。 因此我们每次在push时,需要重新生成一个数组传入,即使用path.slice()

栗子 - 数组总和II

题目描述

算法思路:

以传入参数combinationSum2([10, 1, 2, 7, 6, 1, 5], 8)为栗子进行说明:先将传入的数组candidates进行升序排列, 即candidates = [1,1,2,5,6,7,10], 采用树的深度优先遍历.

  • resides: 离target =8 , 差多少
  • candicates: 当前的用于操作的候选数组
  • path: 当前的路径
  • res: 最终返回的结构

当resides < 0时, 直接退出当前

当resides ===0 时,代表 path中的数组满足条件. 将path推入res中 res.push(path.slice())

当resides > 0 时, 遍历candidates数组:

  • 每次判断 resides - candidates[i] 是否大于0 , 若小于0则进行剪枝(退出当前循环)

  • 同时要考虑[1,2, 5] 和 [1,7]的情况.因为原数组中有2个1, 只需第一个1即可. if(candidate[i] !== candidate[i-1])

  • 到这里就是正常的递归回溯工作了:

    • 每次将 candidates[i]推入path中.
    • 然后调用 dfs()递归
    • 出来回溯. path.pop()
var combinationSum2 = function(candidates, target) {candidates.sort((a, b) => a - b)var res = []function dfs(resides, candidates, path) {if (resides < 0) returnif (resides === 0) res.push(path.slice())for (let i = 0, len = candidates.length; i < len; i++) {if (candidates[i] !== candidates[i - 1]) {if (resides - candidates[i] < 0) breakpath.push(candidates[i])dfs(resides - candidates[i], candidates.slice(i + 1), path)path.pop()}}}dfs(target, candidates, [])return res
}

栗子 - 组合总和 III

题目参考

算法思路: 还是使用深度优先.

  • candidates:当前用于操作的数组
  • path: 当前的路径
  • resides: 当前距离目标的差值

每次进入 dfs:

  • 首先检查条件是否满足:

    • resides若为负数,退出当前环境
    • path.length 若等于 k 则退出当前环境
    • candidates存在且candidates的长度为0,则退出当前环境
  • 然后循环candidates,对于每个candidates[i]

    • 得到当前的path = […path, candidates[i]]
    • 计算当前path长度,若等于k 则判断 resides - candidates[i] 是否为0, 若为0,则将当前路径推入res中。并退出
    • 递归调用 dfs(resides - candidates[i], candidates.slice(i+1), path)
    • 这里需要回溯 path.pop()
var combinationSum3 = function (k, n) {var res = []function dfs(candidates, resides, path) {if ((candidates && candidates.length == 0) || path.length > k || resides < 0) returnfor (let i = 0, len = candidates.length; i < len; i++) {path = [...path, candidates[i]]if (path.length === k && resides - candidates[i] == 0) return res.push(path.slice())dfs(candidates.slice(i + 1), resides - candidates[i], path)path.pop()}}dfs([1, 2, 3, 4, 5, 6, 7, 8, 9], n, [])return res
}

栗子 - 从根到叶子节点数字之和

题目参考

思路:

  • 使用 sum 保存总和, r 保存当前树结构的根节点, path 保存当前的路径(数组类型)
  • 使用dfs深度优先遍历树, 对于每次遍历 dfs(root, path)
    • 判断r 是否为空,若空则返回,否则执行下一步
    • 更新当前的path = […path, r.val]
    • 判断当前是否为叶子节点:
      • 若是则: sum += path.join('') - 0. 其中-0是数字的隐式类型转换
    • dfs(r.left, path)
    • dfs(r.rigth, path)
    • 回溯 path.pop()
var sumNumbers = function (root) {var sum = 0;function dfs(r, val) {if (!r) returnval = [...val, r.val]if (!r.left && !r.right) {return sum += val.join('') - 0}dfs(r.left, val)dfs(r.right, val)val.pop()}dfs(root, '')return sum
};

栗子 - 路径总和II

题目参考

算法思路:大体的思路是深度优先遍历,遍历顺序5 -> 4 -> 11 -> 7 --> 11 -> 2 --> 11 --> 4 -->5

其中,->代表下一个-->代表回退。递归循环调用dfs函数.传入当前的树结构的根节点r、距离总和差值resides和当前的路径path

每次dfs循环如下:

  • 判断r是否为null, 若是则返回
  • 生成当前的path.
  • 判断 resides - r.val 是否为0
    • 若为0,则判断当前是否是叶子节点
  • dfs 当前节点的左节点和右节点
var pathSum = function(root, sum){var res = []function dfs(resides, r, path){if(!r) returnpath = [...path, r.val]		// 这里使用[]隐式规则,在新的内存空间中生成了一个数组if(resides - r.val === 0 && !r.left && !r.right) return res.push(path)dfs(resides - r.val, r.left, path)dfs(resides - r.val, r.right, path)}dfs(sum, root, [])return res
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250256.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

013.Zabbix的Items(监控项)

一 Items简介 Items是从主机里面获取的所有数据&#xff0c;可以配置获取监控数据的方式、取值的数据类型、获取数值的间隔、历史数据保存时间、趋势数据保存时间、监控key的分组等。通常情况下item由key参数组成&#xff0c;如监控项中需要获取cpu信息&#xff0c;则需要一个对…

Cookie 和 Session的区别

pass 下次再写转载于:https://www.cnblogs.com/nieliangcai/p/9073520.html

算法 --- 记一道面试dp算法题

题目: 给定一个数组(长度大于1),如下 let a [1,4,3,4,5] // 长度不确定,数值为整数要求写一个函数,返回该数组中,除本身数字之外其他元素的成积.即返回如下: // 过程[4*3*4*5, 1*3*4*5, 1*4*4*5, 1*4*3*5, 1*4*3*4] // 结果[240, 60, 80, 60, 48]题目要求不使用除法,且时间…

编码

一、什么是编码&#xff1f;首先&#xff0c;我们从一段信息即消息说起&#xff0c;消息以人类可以理解、易懂的表示存在。我打算将这种表示称为“明文”&#xff08;plain text&#xff09;。对于说英语的人&#xff0c;纸张上打印的或屏幕上显示的英文单词都算作明文。其次&a…

ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(10)之素材管理

源码下载地址&#xff1a;http://www.yealuo.com/Sccnn/Detail?KeyValuec891ffae-7441-4afb-9a75-c5fe000e3d1c 素材管理模块也是我们这个项目的核心模块&#xff0c;里面的增删查改都跟文章管理模块相同或者相似&#xff0c;唯一不同点可能是对附件的上传处理&#xff0c;但…

javascript --- [express+ vue2.x + elementUI]登陆的流程梳理

说明 涉及到以下知识点: 登陆的具体流程express、vue2.x、elementUI、axios、jwt、assert 登陆方面的API使用中间件的使用前后端通过http状态码,进行响应的操作(这里主要是401)密码验证(bcrypt的hashSync方法对明文密码进行加密,compareSync方法对加密的密码进行验证)token的…

设计模式---装饰模式

今天学习了装饰模式&#xff0c;做个笔记。。装饰模式的基础概念可以参考&#xff1a;https://blog.csdn.net/cjjky/article/details/7478788 这里&#xff0c;就举个简单例子 孙悟空有72变&#xff0c;但是它平时是猴子&#xff0c;遇到情况下&#xff0c;它可以变成蝴蝶等等 …

springMvc 注解@JsonFormat 日期格式化

1&#xff1a;一定要加入依赖,否则不生效&#xff1a; <!--日期格式化依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version>&…

Git很简单--图解攻略

Git Git 是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09;作用 源代码管理为什么要进行源代码管理? 方便多人协同开发方便版本控制Git管理源代码特点 1.Git是分布式管理.服务器和客户端都有版本控制能力,都能进行代码的提交、合并、. 2.Git会在根…

css --- 使用scss生成常用的基本css样式

"工具样式"的概念和 SASS(SCSS) 在webpack中使用sass 安装sass和sass-loader $ npm i sass sass-loader由于使用了脚手架,安装完毕后重启前端即可 样式重置 其实就是样式的初始化 // reset* {box-sizing: border-box; // 以边框为准. css3盒模型outline: none;…

vc/vs开发的应用程序添加dump崩溃日志转

原贴地址&#xff1a;https://blog.csdn.net/wangkui1331/article/details/78029940 vc/vs开发的应用程序出现崩溃的时候&#xff0c;由于没有任何记录&#xff0c;导致开发人员很难追踪&#xff0c;但是添加dump文件后&#xff0c;就可以免除这些烦恼 1.添加方法 &#xff08;…

51 nod 1127最短的包含字符串(尺取法)

1127 最短的包含字符串 收藏关注给出一个字符串&#xff0c;求该字符串的一个子串S&#xff0c;S包含A-Z中的全部字母&#xff0c;并且S是所有符合条件的子串中最短的&#xff0c;输出S的长度。如果给出的字符串中并不包括A-Z中的全部字母&#xff0c;则输出No Solution。Input…

Java --- 基础学习Ⅰ

第一章 开发前言 位、字节 位(bit): 一个数字0或一个数字1,代表一位 字节(Byte): 每逢8位是一个字节,这时数据存储的最小单位 1 Byte 8 bit 1 KB 1024 Byte 1 MB 1024 KB 1 GB 1024 MB 1 TB 1024 GB 1 PB 1024 TB MS-DOS(Microsoft Disk Operating System) 第二章 Ja…

JSON 数据重复 出现$ref

JSONArray 类型 如果我们往里面add数据的时候 如果数据相同&#xff0c;那么就会被替换成 $ref: 也就是被简化了 因为数据一样所直接 指向上一条数据 循环引用&#xff1a;当一个对象包含另一个对象时&#xff0c;fastjson就会把该对象解析成引用。引用是通过$ref标示的&am…

Java --- 基础学习Ⅱ

继承 继承概述 下面有一个学生类 public class Student{private String name;private int age;public void study(){System.out.println("努力学习了");}public String getName() {return name;}public void setName(String name) {this.name name;}public int g…

urllib库

python内置的最基本的HTTP请求库&#xff0c;有以下四个模块&#xff1a; urllib.request  请求模块 urllib.error    异常处理模块 urllib.parse   url解析模块 urllib.robotparser robots.txt解析模块 urllib.request请求模块&#xff1a; urllib.request.urlopen(u…

layer的删除询问框的使用

删除是个很需要谨慎的操作 我们需要进行确认 对了删除一般使用ajax操作 因为如果同url请求 处理 再返回 会有空白页 1.js自带的样式 <button type"button" data-toggle"tooltip" title"删除" class"btn btn-danger pull-right btn-xs&qu…

文献笔记(八)

一、基本信息 标题&#xff1a;MySQL数据库在自动测试系统中的应用 时间&#xff1a;2017 出版源&#xff1a;宁夏职业技术学院 领域分类&#xff1a;无线互联科技 二、研究背景 问题定义&#xff1a;文章介绍了MySQL数据库的特点&#xff0c;结合自动测试系统运行中的实际&…

Java --- 常用API

常用API 方法重载: 方法名相同,方法接收的参数不同 static: 修饰的类,可以直接使用类名进行调用 方法名说明public static abs(int a)返回参数的绝对值public static double ceil(double a)返回大于或等于public static double floor(double a)返回小于或等于参数的最大doubl…

9. 弹出键盘挡住input

1.) react 中 <input className"inp3" placeholder"密码" type"password" onChange{this.changepassword.bind(this)} onFocus{this.FocusFN.bind(this)} value{this.state.paswword}/> FocusFN(){ setTimeout(()>{ let pannel docume…