如何判断一个题目用“贪心/动态规划“还是用“BFS/DFS”方法解决

1 总结

1.1 贪心、动态规划和BFS/DFS题解的关系

一般能使用贪心、动态规划解决一个问题时,使用BFS,DFS也能解决这个题,但是反之不能成立。

1.2

2 贪心 -> BFS/DFS

2.1 跳跃游戏1和3的异同

这两道题,“跳跃游戏”(题号 55)和“跳跃游戏 III”(题号 1306),虽然都是关于跳跃问题的,但它们的规则和解题策略有显著的不同。下面是它们的主要异同点:

2.1.1 跳跃游戏(题号 55)

  1. 问题描述:给定一个非负整数数组 nums,你最初位于数组的第一个下标。数组中的每个元素代表你在该位置可以跳跃的最大长度。需要判断是否能够到达最后一个下标。

  2. 跳跃规则:从任意位置 i,可以向前跳跃 0nums[i] 的任意步数。

  3. 目标:到达数组的最后一个下标。

  4. 解题策略:通常使用贪心算法。从左到右遍历数组,更新能够到达的最远位置。如果最远位置超过或等于最后一个下标,则返回 true

2.1.2 跳跃游戏 III(题号 1306)

  1. 问题描述:这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]

  2. 跳跃规则:从任意位置 i,只能向前跳到 i + arr[i] 或向后跳到 i - arr[i]

  3. 目标:跳到任何一个元素值为 0 的下标处。

  4. 解题策略:通常使用深度优先搜索(DFS)或广度优先搜索(BFS)。由于跳跃方向可以正向也可以反向,需要记录访问过的位置以防止无限循环。

2.1.3 它们的异同点

  • 跳跃方向和范围

    • 在“跳跃游戏”中,跳跃只能向前,且范围在 0nums[i] 之间。
    • 在“跳跃游戏 III”中,跳跃可以向前或向后,且步数固定为 arr[i]
  • 目标不同

    • “跳跃游戏”的目标是到达数组的最后一个下标。
    • “跳跃游戏 III”的目标是到达任一元素值为 0 的下标。
  • 解题策略

    • “跳跃游戏”通常用贪心算法解决。
    • “跳跃游戏 III”则更适合使用DFS或BFS,因为它涉及到多个可能的跳跃方向和回溯。

这两个问题虽然在表面上看起来类似,但实际上涉及到的算法思维和解决方法有很大的区别。

2.2 LC55. 跳跃游戏(贪心)

在这里插入图片描述

    public boolean canJump(int[] nums) {int n=nums.length;int e=0;boolean res=true;for(int i=0;i<n;i++){if(i>e){res=false;break;}e=Math.max(e, i+nums[i]);}return res;}

2.3 LC1306. 跳跃游戏 III

在这里插入图片描述

class Solution {public boolean canReach(int[] arr, int start) {int n=arr.length;boolean[]vis=new boolean[n];return dfs(arr,start,vis);}boolean dfs(int[] arr, int start,boolean[]vis){vis[start]=true;if(arr[start]==0){return true;}int rm=arr[start]+start;int lm=start-arr[start];boolean l=false;boolean r=false;if(rm<arr.length&&!vis[rm])l=dfs(arr,arr[start]+start,vis);if(lm>=0&&!vis[lm])r=dfs(arr,start-arr[start],vis);return l||r;}// bfs方法解题public boolean canReach2(int[] arr, int start) {int n=arr.length;Deque<Integer>st=new LinkedList<>();st.addLast(start);boolean[]vis=new boolean[n];while(!st.isEmpty()){int poll=st.pollLast();vis[poll]=true;if(arr[poll]==0){return true;}if(poll+arr[poll]<n&&!vis[poll+arr[poll]])st.addLast(poll+arr[poll]);if(poll-arr[poll]>=0&&!vis[poll-arr[poll]])st.addLast(poll-arr[poll]);}return false;}
}

2.4 LC1345. 跳跃游戏 IV

2.4.1 答案:为什么minJumps2超时了?


class Solution {public int minJumps(int[] arr) {Map<Integer, List<Integer>> idxSameValue = new HashMap<Integer, List<Integer>>();for (int i = 0; i < arr.length; i++) {idxSameValue.putIfAbsent(arr[i], new ArrayList<Integer>());idxSameValue.get(arr[i]).add(i);}Set<Integer> visitedIndex = new HashSet<Integer>();Queue<int[]> queue = new ArrayDeque<int[]>();queue.offer(new int[]{0, 0});visitedIndex.add(0);while (!queue.isEmpty()) {int[] idxStep = queue.poll();int idx = idxStep[0], step = idxStep[1];if (idx == arr.length - 1) {return step;}int v = arr[idx];step++;if (idxSameValue.containsKey(v)) {for (int i : idxSameValue.get(v)) {if (visitedIndex.add(i)) {queue.offer(new int[]{i, step});}}idxSameValue.remove(v);}if (idx + 1 < arr.length && visitedIndex.add(idx + 1)) {queue.offer(new int[]{idx + 1, step});}if (idx - 1 >= 0 && visitedIndex.add(idx - 1)) {queue.offer(new int[]{idx - 1, step});}}return -1;}public int minJumps2(int[] arr) {int n=arr.length;Map<Integer,List<Integer>>mp=new HashMap<>();for(int i=0;i<n;i++){List<Integer>ls=mp.getOrDefault(arr[i],new ArrayList<>());ls.add(i);mp.put(arr[i],ls);}Deque<Integer>q=new LinkedList<>();q.offerLast(0);int ans=0;boolean[]vis=new boolean[n];while(!q.isEmpty()){int size=q.size();for(int i=0;i<size;i++){int poll=q.pollFirst();if(poll==n-1){return ans;}if(poll+1<n&&!vis[poll+1]){vis[poll+1]=true;q.offerLast(poll+1);}if(poll-1>=0&&!vis[poll-1]){vis[poll-1]=true;q.offerLast(poll-1);}List<Integer>t=mp.get(arr[poll]);for(int j=0;j<t.size();j++){if(!vis[t.get(j)]&&t.get(j)!=poll){vis[t.get(j)]=true;q.offerLast(t.get(j));}}}ans++;}return -1;}
}

让我们分析这两个方法 minJumpsminJumps2 的不同之处,以了解为什么 minJumps2 会超时。

2.4.2 方法 minJumps

  1. 数据结构:使用 HashMapHashSet 来存储相同值的索引和已访问的索引。使用 Queue 来进行广度优先搜索(BFS)。
  2. 访问控制:通过 visitedIndex(一个 HashSet)控制访问,一旦访问过某个索引,就不会再访问。
  3. 优化处理:在访问完所有相同值的索引后,使用 idxSameValue.remove(v) 来移除这个值,从而减少后续的无效搜索。

2.4.3 方法 minJumps2

  1. 数据结构:使用类似的 HashMap 来存储相同值的索引。使用 Deque(双端队列)进行BFS。
  2. 访问控制:通过一个 boolean 数组 vis 控制访问,记录已访问的索引。
  3. 重复检查:方法中没有移除已经访问过的值的索引集合,这意味着即使某个值的所有索引都已经被访问,它们仍然会在后续的搜索中被重复检查。

2.4.4 为什么 minJumps2 超时

原因可能在于 minJumps2 没有像 minJumps 那样有效地减少搜索空间。在 minJumps 中,一旦一个值的所有可能的跳跃位置都被探索过,这个值就会从 idxSameValue 中移除,从而避免了对这些位置的重复搜索。而 minJumps2 没有这样的优化,因此在遇到具有大量相同值的数组时,它会进行许多不必要的重复检查,这可能导致超时。

另外,虽然 minJumpsminJumps2 都是BFS实现,但由于对搜索空间的处理方式不同,两者在面对大规模数据时的性能表现会有显著差异。在这种情况下,减少无效的重复搜索是优化算法和避免超时的关键。

2.5 方法二改进

public int minJumps(int[] arr) {int n=arr.length;Map<Integer,List<Integer>>mp=new HashMap<>();for(int i=0;i<n;i++){List<Integer>ls=mp.getOrDefault(arr[i],new ArrayList<>());ls.add(i);mp.put(arr[i],ls);}Deque<Integer>q=new LinkedList<>();q.offerLast(0);int ans=0;boolean[]vis=new boolean[n];while(!q.isEmpty()){int size=q.size();for(int i=0;i<size;i++){int poll=q.pollFirst();if(poll==n-1){return ans;}if(poll+1<n&&!vis[poll+1]){vis[poll+1]=true;q.offerLast(poll+1);}if(poll-1>=0&&!vis[poll-1]){vis[poll-1]=true;q.offerLast(poll-1);}if(mp.containsKey(arr[poll])){List<Integer>t=mp.get(arr[poll]);for(int j=0;j<t.size();j++){if(!vis[t.get(j)]&&t.get(j)!=poll){vis[t.get(j)]=true;q.offerLast(t.get(j));}}mp.remove(arr[poll]);}}ans++;}return -1;}

3 dp -> BFS/DFS

3.1

3.2 LC64. 最小路径和

3.3 LC64 改编题:在一个m*n的矩阵中从(i,j)点开始走,每一次可以走上下左右四个方向,每走一步都会消耗m[x][y]体力,请问到达目标节点(t1,t2)最少需要耗费多少体力,lc上应该有这样类似的题目,列举出来。使用DFS或者BFS。

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

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

相关文章

html实现各种瀑布流(附源码)

文章目录 1.设计来源1.1 动态响应瀑布流1.2 分页瀑布流1.3 响应瀑布流 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/134613121 html实现各种瀑布流(附源码)&#xff0c;…

100元预算,轻松涨粉1000!腾讯运营面试秘籍大揭秘!

大家好啊&#xff01;小米在这里&#xff5e; 很高兴又有机会和大家见面啦&#xff01;最近小米参加了一场腾讯的运营面试&#xff0c;遇到了一个超有趣的问题&#xff1a;如果让你运营一个公众号&#xff0c;近期需要增加1000个关注&#xff0c;预算100元&#xff0c;怎么完成…

【阿里云】图像识别 智能分类识别 项目开发(一)

语音模块和阿里云图像识别结合 环境准备 代码实现 编译运行 写个shell脚本用于杀死运行的进程 语音模块和阿里云图像识别结合 使用语音模块和摄像头在香橙派上做垃圾智能分类识别 语音控制摄像下载上传阿里云解析功能点实现 环境准备 将语音模块接在UART5的位置 在orange…

数据结构总复习

文章目录 线性表动态分配的顺序存储结构链式存储 线性表 动态分配的顺序存储结构 通过分析代码&#xff0c;我们发现&#xff0c;要注意什么&#xff1a; 要分清你的下标Insert 函数是可以用来没有元素的时候&#xff0c;增加元素的Init(或者Create )函数一般只用来分配空间…

go atexit源码分析

文章目录 atexit源码解析UML类图样例一: 程序退出之前执行注册函数1.1 流程图1.2 代码分析 样例二&#xff1a;使用cancel取消注册函数2.1 cancel流程图2.2 代码分析 样例三&#xff1a;使用Fatal/Fatalln/Fatal执行注册函数3.1 Fatal/Fatalln/Fatal流程图3.2 代码分析 atexit源…

Android平台GB28181设备接入模块开发填坑指南

技术背景 为什么要开发Android平台GB28181设备接入模块&#xff1f;这个问题不再赘述&#xff0c;在做Android平台GB28181客户端的时候&#xff0c;媒体数据这块&#xff0c;我们已经有了很好的积累&#xff0c;因为在此之前&#xff0c;我们就开发了非常成熟的RTMP推送、轻量…

Scannet v2 数据集介绍以及子集下载展示

Scannet v2 数据集介绍以及子集下载展示 文章目录 Scannet v2 数据集介绍以及子集下载展示参考数据集简介子集scannet_frames_25kscannet_frames_test 下载脚本 download_scannetv2.py 参考 scannet数据集简介和下载-CSDN博客 scannet v2 数据集下载_scannetv2数据集_蓝羽飞鸟的…

BeanUtil的正确使用方式

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 在实际的开发中&#xff0c;我们常常会用到工具类去拷贝对象的属性&#xff0c;将一个对象的属性转换成另外一个…

球面的表面积

此推导需要用到重积分的知识&#xff0c;另外关于曲面的面积公式可以看我之前的博客

百度AI布局:从财报看百度的核心竞争力和未来发展方向

百度是中国最大的搜索引擎&#xff0c;也是全球领先的人工智能&#xff08;AI&#xff09;公司。百度在2023年第三季度业绩中&#xff0c;展示了其在AI领域的强劲表现和广阔前景。 百度财报透露了关于AI业务的哪些重要信息&#xff1f; 百度在2023年第三季度的财报中&#xf…

机器学习:攻击方法FGSM系列

任务 FGSM I-FGSM MI-FGSM Ensemble Attack 攻击评价指标 准确率越低表明攻击越好 数据 预训练模型 BaseLine 实践

***Linux常用命令及解释

1、查看Linux的版本信息 1.1、uname -a 1.2、cat /etc/issue 1.3、cat /proc/version 1.4、hostnamectl 通过使用hostnamectl命令&#xff0c;可以查询和更改系统主机名&#xff0c;并且还可以查看Linux的发行版和内核版本。 2、删除文件 3、修改目录权限 4、解压文件 5、…

探索 Linux vim/vi 编辑器:介绍、模式以及基本操作演示

&#x1f490;作者&#xff1a;insist-- &#x1f490;个人主页&#xff1a;insist-- 的个人主页 理想主义的花&#xff0c;最终会盛开在浪漫主义的土壤里&#xff0c;我们的热情永远不会熄灭&#xff0c;在现实平凡中&#xff0c;我们终将上岸&#xff0c;阳光万里 ❤️欢迎点…

Spring的依赖注入,依赖注入的基本原则,依赖注入的优势

文章目录 Spring的依赖注入依赖注入的基本原则依赖注入有什么优势查找定位操作与应用代码完全无关。有哪些不同类型的依赖注入实现方式&#xff1f;构造器依赖注入和 Setter方法注入的区别 Spring的依赖注入 控制反转IoC是一个很大的概念&#xff0c;可以用不同的方式来实现。…

android系统新特性——用户界面以及系统界面改进

用户界面改进 Android用户界面改进最明显的就是MD了。MD是Google于2014年推出的设计语言&#xff0c;它是一套完整的设计系统&#xff0c;包含了动画、样式、布局、组件等一系列与设计有关的元素。通过对这些行为的描述&#xff0c;让开发者设计出更符合目标的软件&#xff0c…

vue3+elementPlus之侧边菜单栏功能

选择默认的颜色&#xff0c;将代码拷贝至<el-aside>模块中 稍微把不需要的修改一下。 <template><div class"common-layout"><el-container><el-header class"homeHeader"><div class"headerTitle">Devops…

vue怎么实现国际化? vue-i18n 插件实现国际化,支持切换不同语言

依赖的文档开始 | Vue I18n 一、安装 npm install vue-i18n 如果在一个模块系统中使用它&#xff0c;你必须通过 Vue.use() 明确地安装 vue-i18n&#xff1a; import Vue from vue import VueI18n from vue-i18nVue.use(VueI18n)二、使用 在 src 下创建 lang 文件夹 1.准…

实现【Linux--NTP 时间同步服务搭建】

实现【Linux--NTP 时间同步服务搭建】 &#x1f53b; 前言&#x1f53b; 一、NTP 校时&#x1f530; 1.1 NTP 服务校时与 ntpdate 校时的区别&#x1f530; 1.2 NTP 校时服务搭建&#x1f530; 1.2.1 确认 ntp 的安装&#x1f530; 1.2.2 配置 ntp 服务&#x1f530; 1.2.3 启动…

大数据面试大厂真题【附答案详细解析】

1.Java基础篇&#xff08;阿里、蚂蚁、字节、携程、快手、杭州银行等&#xff09; 问题&#xff1a;HashMap的底层实现原理 答案&#xff1a; 在jdk1.8之前&#xff0c;hashmap由 数组-链表数据结构组成&#xff0c;在jdk1.8之后hashmap由 数组-链表-红黑树数据结构组成&…

openpnp - 给底部相机加防尘罩

文章目录 openpnp - 给底部相机加防尘罩概述笔记END openpnp - 给底部相机加防尘罩 概述 设备标定完, 看着底部相机, 有点担心掉进去东西, 万一从吸嘴掉下去的料(或者清理设备台面时, 不小心掉进去东西)将顶部相机搞短路怎么办. 就想加个防尘罩, 如果有东西掉进去, 可以掉到机…