【编程算法】跳跃游戏ⅠⅡⅢ(Python解法)

2023-05-16

写这篇文章源于之前4.10做的字节跳动的笔试,第二道编程题就是跳跃游戏类,可以说和牛客或者力扣上边的解题做法是完全一样的,可惜当时我才刚开始学习算法。深入了解该类型后发现真的很有意思,这篇文章给大家分享一下本人的思路及解题方法,算是系统性地阐述了该类问题的解法,假如把这几题搞懂,我觉得在遇到该类问题便能做到得心应手了。

目录

一、贪心算法

二、跳跃游戏Ⅰ

题目描述:

 解题思路:

 解法1:

解法2:

三、拓展问题

1、固定跳跃游戏:

2、跳跃游戏Ⅱ(最少步数/次数):

3、跳跃游戏Ⅲ(最佳路径)

总结


一、贪心算法

贪心算法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下最好/最优的选择(局部最有利的选择),并以此希望最后堆叠出的结果也是最好/最优的解。

对于跳跃问题来说,贪心算法是不错的选择,跳跃问题需要你每次做出选择,并选择能带来更多收益的位置,可通过for/while遍历+条件语句来解决,常规具体步骤:

步骤1:从某个初始解出发;

步骤2:采用迭代的过程,当可以向目标前进一步时,就根据局部最优策略,得到一部分解,缩小问题规模;

步骤3:将所有解综合起来。

二、跳跃游戏Ⅰ

题目描述:

字节跳动题目:给定一个非负整数数组nums,例如:[2,0,1,0,3],位置上的数值代表了能量值的多少,给定机器人初始位于第一个位置,机器人走一步,需要消耗1个单位能量,如果当前位置能量为0,则无法走了。arr每个位置就是能量值arri,机器人可以选择走0–arri步,请问你机器人能走到终点N位置吗?

示例:

输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。

输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。

其实字节的题目只是跳跃游戏的变形,不信你看跳跃游戏的原题👇(来自牛客)

 解题思路:

其实做算法题重要的理解他的逻辑,看下图,初始位置是index=0,nums=2,那么可以选择跳一次或者两次,假如选择跳一次,那么跳到index=2,由于nums=1,再跳一次...最后到达队尾;假如选择跳二次,先跳到index=1,再选择跳三次就可直接到达队尾。(跳跃后,不论选择跳几次,下一次的跳跃以index上的nums为准)

 解法1:

1.这题存在一个核心参数,那就是max_pos,它是指当前能跳到最远的位置,max_pos = index + nums[index],坐标和数值的和决定了它能跳多远。参考上图,index=0时,他的max_pos=2,最远能跳到index=2,index=2时,它的max_pos=3,最远能跳到index=3,只有掌握了这个参数才能明白此解法。


for index in range(n): 
    if index <= max_pos and index + nums[index] > max_pos: 
        max_pos = index + nums[index]  

2.还有一个关键的循环和条件语句👆,因为数组本身是不存在坐标的,因此通过len(nums)=4,for循环相当于遍历0,1,2,3,4;

3.index必须小于等于max_pos,因为max_pos的值是它能跳到最远的位置;并且index和该位置的值只有大于max_pos时,才能跳到更远的位置,不然就没意义了,比如(index=3,nums=2)、(index=4,nums=0)、(index=5,nums=1),max_pos=4(它位于前者),后者的index + nums[index]也等于4,如果它跳过去游戏也就结束了,因此选择跳到idex=5是更好的选择。这相当于是一个选择的过程,看选择哪一个index会带来最大的资源(max_pos),更新完后max_pos就是新的值了,这在算法中是非常常见的,然后进行新的循环,直至max_pos到达队尾—len(nums)。

个人见解:通过for循环+条件模拟贪心算法—计算较为跳跃,while适合动态规划—比如斐波那契数列

class Solution:
    def canJump(self, nums) : #灵活跳
        max_pos = 0 #1.初始化当前能跳到最远的位置
        for index in range(n): #遍历nums中的每个位置
            if index <= max_pos and index + nums[index] > max_pos: #判断index位置是否可跳
                max_pos = index + nums[index] #更新max_pos
            if index >max_pos: #加上可提前断言结束
                return False
        return max_pos >= len(nums)-1

解法2:

解法1和解法2的关键其实都在于贪心算法,在每次做出选择时都使max_pos获取更大的值,以供下次选择能够拥有更多的资源进行选择。

解法2不同的点在于他利用enumerate()函数将数组重新组合为一个索引序列[(0,2),(1,3),(2,1),(3,1),(4,4)](注意enumerate(nums)类型是enumerate,无法直接打印,同map()一样,导出需要list(..)操作,但是遍历时可直接赋值),便于理解和操作,相比解法2,解法1确实挺费脑子的。

class Solution:
    def canjump(self, nums):
        max_pos = 0  # 初始化
        for index, jump in enumerate(nums):  # 以每组形式遍历-index=0,jump=2、index=1,jump=3...
            if index <= max_pos and index + jump > max_pos:  # 判断idex位置是否可跳
                max_pos = index + jump  # 更新最远能到达位置
            if index > max_pos:
                return False
        return max_pos >= len(nums)-1

三、拓展问题

1、固定跳跃游戏:

题目描述同上,但要求每次固定按位置里边的能量值跳跃,问能否到达数组最后一个位置。

这题是本人的一个脑洞,思路也比上边步数这题简单很多,对于解法1/2的算法稍作变动,因为机器人无法做出选择,只能按照位置里边的数值进行跳跃,少了index + jump > max_pos的限制条件👇

1.初始化max_pos:所能到达的最远位置

2.通过enumerate()函数给nums建立索引序列列表,index,jump赋值,for循环遍历

3.条件语句,跳的位置是其能跳到的最远的位置,跳完后更新max_pos

4.断言max_pos是否到达队尾

class Solution:
    def canjump_fix(self, nums):  # 固定跳
        max_pos = 0
        n = len(nums)-1
        for index,jump in enumerate(nums):
            if index == max_pos:
                max_pos = index+jump
        return max_pos >= n

2、跳跃游戏Ⅱ(最少步数/次数):

题目描述同上,但保证每次都能到达队尾,要求输出运动最少的步数。

1.方法沿用上边的解法2,因为前边的解法不是最优路径(遍历位置,max_pos每次选择时更进一步,并不是一步到位的),因此增加参数end、start,增加限制条件(在每次选择时给他限制一个范围),同时while循环多次遍历数组,直至能跳出或跳到队尾结束循环。

2.end:边界,每次做出选择时能跳到最远的距离;start:起始位置,每次做出选择时的起始位置;每次while循环时,机器人只能在(start, end + 1)间选择跳哪里,然后在该范围内选择资源最多的位置,因此每次遍历都能跳到资源最多的位置。

3.start,end,step是会随着while循环的次数变化,start请看下边的逻辑,end的值更新,step增加一次,这主要是看while循环的次数。

这里比较绕的可能是两层循环,第一层是while循环,第二层是for循环,比如end=0(初始位置),n=5,①开始第一次while循环,然后for循环对序列(解法2详述)进行遍历,附加三个条件,条件1限制跳的范围,条件2、3确保跳到一个资源更多的位置(也不是一步到位,类似解法1、2),可能进行多次比较后,机器人在范围内跳到了资源最多的位置(index + jump最大),那么可算作一次最优选择,step+1 ②start和end变换位置,这点比较关键,因此做了图方便大家理解👇,其实start取值<上次选择的den即可,不影响。

class Solution:
    def canjump_step(self, nums):
        max_pos = 0
        start,end,step = 0,0,0 #三参数初始化简化写法
        n = len(nums)-1 #因为len()不包含0,和index有冲突,因此-1
        while end < n: #跳到最后一位可忽略,不用增加次数
            for index, jump in enumerate(nums):  #增加一个条件
                if index in range(start, end + 1) and\
                   index <= max_pos and\
                   index + jump > max_pos:
                    max_pos = index + jump  
            start,end,step = end,max_pos,step+1  #参数变化简化写法
        return step        

3、跳跃游戏Ⅲ(最佳路径)

题目描述同上,也保证每次都能到达队尾,要求输出运动最优的路径。

解此题的思路类似跳跃游戏Ⅱ,将步数换成了路径,还是沿用之前的解法,因为每次while循环只能得到选择范围内最大的max_pos,并不能获取跳到了哪个具体位置。但我们能利用这个每次while循环的max_pos,新建一个空的path_max表,将每次while循环后的max_pos填入,这样就得到了机器人的路径的初始表(所走路径上的max_pos=index+jump)。

然后再新建一个空的path表,将path_max表与索引序列里的值进行比对,如下图,实现方法:可先通过for循环遍历path_max,并与索引序列进行比对(index+jump == path_max[i]),如果比对成功使得path_max的遍历起始位置向右移动一位,即可满足。

class Solution:
    def canjump_path(self, nums):
        max_pos = 0
        path_max = []
        path = []
        start,end,n=0,0,len(nums)-1
        while end < n:
            for index,jump in enumerate(nums):
                if index in range(start,end+1) and\
                   index <= max_pos and\
                   index + jump > max_pos:
                    max_pos = index + jump
            start,end = end,max_pos
            path_max.append(max_pos)
        i = 0
        for index, jump in enumerate(nums):
            for j in range(i,len(path_max)):
                if index+jump == path_max[i]:
                    path.append(index)
                    i = i+1
        return path


总结

困扰好久的跳跃问题终于结束了,大家如果有疑问都可以评论提出,有不足之处请大家批评指正,希望能多结识这方面的朋友,共同学习、共同进步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【编程算法】跳跃游戏ⅠⅡⅢ(Python解法) 的相关文章

  • Spring框架系列之bean的生命周期底层原理06

    bean的生命周期 xff0c 咱们必须从 AnnotationConfigApplicationContext的getBean方法开始 xff0c getBean顾名思义就是从Spring容器中得到一个Bean的实例对象 xff0c Sp
  • 电信运营商移动互联网发展分析

    电信运营商移动互联网发展分析 移动互联网是通信业发展的大趋势 xff0c 随着3G 和WiMAX 等高速无线接入技术的飞速发展 xff0c 移动互联网不仅继承固定互联网的很多技术 xff0c 并且在商务 娱乐以及移动性等方面拓展用户需求 自
  • Spring框架系列之bean的生命周期底层原理07

    上一篇我们预留了两个大的内容 xff0c 一个是Object sharedInstance 61 getSingleton beanName 从单例池中获取数据 xff0c 另外一个是getSingleton方法创建单例Bean xff0c
  • Spring框架系列之bean的生命周期底层原理08

    接着上一篇 xff0c 咱们继续doCreateBean方法的分析 xff0c doCreateBean内容比较多 xff0c 我们这次主要是把它的整体流程说下 xff0c 后续会逐个来分析每一个关键点 代码如下 xff1a protect
  • 2020-09-25 Python基础学习第三天笔记

    文章目录 一 可变字符串二 运算符三 列表1 列表的创建2 列表常用命令3 多维列表 四 元组 2020 9 24 Day3 一 可变字符串 需要原地修改字符串 xff0c 可以使用 io StringIO 对象或 array 模块 spa
  • Python Cookbook学习总结

    第一章 xff1a 数据结构和算法 任何序列 xff08 可迭代的对象 xff09 都可以通过一个简单的赋值操作来分解为单独的变量 xff0c 唯一的要求是变量的总数和结构要与序列相吻合 xff08 比如对于存储二维坐标等的二维数组 xff
  • SpringBoot解析yml/yaml/properties配置文件的四种方式汇总

    目录 一 配置文件注入方式一 64 Value 二 配置文件注入方式二 64 ConfigurationProperties 三 自定义解析类 xff0c 直接暴力读取yml配置文件 四 Spring配置文件的解析类Environment获
  • Linux下配置Apache为多端口 (centos7)

    apache设置多个不同的端口 xff0c 映射不同的文件 一 xff1a vim etc httpd conf httpd conf 查看http配置文件 滑倒最底部 xff0c 箭头标注的位置 我们需要进入该目录编辑 二 xff1a c
  • android11.0上通过广播屏蔽电源键功能

    framework base services core java com android server policy PhoneWindowManager java import java util HashSet import java
  • python和matlab实现随机攻击网络节点+蓄意攻击网络节点,实现最大连通子图比例、网络效率变化、平均距离变化等等。

    首先要有自己的邻接关系 xff0c 最好是邻接表 xff0c 如下图这样包括起点和终点 要在网络中读取自己的文件 xff0c 生成自己的复杂网络图 知道攻击方式包括哪些 xff1a 比如度 介数等 xff0c 选择自己想要的攻击方式 在研究
  • 2021-05-22

    第一个作业 xff1a 使用python编写一个数学表达式 注意 43 的运算顺序 xff0c 可以使用括号改变运算顺序 xff0c 和数学运算一样 第二个作业 xff1a 使用输入函数input xff08 提示符 xff09 xff0c
  • JavaScript变量的命名规则和命名规范

    变量的命名规则和命名规范 1 规则 你必须遵守 不然报错 1 1 一个变量只能由 数字 0 9 字母 a zA Z 美元符 划线下 组成 1 2 一个变量不能由 数字 开头 1 3 再 JS 中严格区分大小写 61 gt num Num N
  • 不惧掉签 | 苹果IPA安装包,免费自签教程

    最近连续更新了好几款 TikTok xff0c 基本上是刚更新没两天就掉签 大家也知道 xff0c 苹果的软件不像安卓 未上架App Store的软件只能签名后才能正常安装 不过 xff0c 好在国民手机管理软件 爱思助手 客户端也加入了
  • JavaScript把其他数据类型转换成字符串类型

    数据类型转换 转字符串 把其他数据类型转换成字符串类型 1 String 43 语法 String 你要转换的数据 43 返回值 转换好的数据 43 特点 61 gt 任何数据类型都能转换 2 toString 43 语法 你要转换的数据
  • JavaScript条件分支语句-switch语句

    条件分支语句 switch 43 语法 switch 要判断的变量 case 情况1 情况1执行的代码 break case 情况2 情况2执行的代码 break default 所有条件都不满足的时候执行的代码 43 注意 1 我们的每一
  • JavaScirpt - arguments

    arguments 43 在函数内部天生自带的变量 43 表示所有实参的集合 伪数组 arguments 的属性 1 length 61 gt 表示长度 arguments 里面由多少个数据 61 gt 其实就是你的函数调用由多少个实参 6
  • 简版弹幕实现。HTML+CSS+JAVASCRIPT

    思路 xff1a 1 设置video 2 设置输入框 3 获取输入框的内容 xff0c 添加 删除和更新 4 里面运用了单厂模式 xff0c 每次生成的例子都是一样的 span class token doctype lt DOCTYPE
  • webpack 模块加载原理

    webpack webpack 原理 1 webpack 模块加载原理 文件信息来源 xff1a webpack 深入理解模块加载原理 webpack 是一个模块打包器 xff0c 在它看来 xff0c 每一个文件都是一个模块 1 1 Co
  • 使用 FSL 和 TrackVis 分析 DTI 数据

    转载原文 使用 FSL 和 TrackVis 分析 DTI 数据 Alex 2018 05 21 free learner 64 163 com 弥散加权成像 xff08 Diffusion Weighted Imaging DWI xff
  • Java Swing界面设计UI(全)

    原文链接 http blog csdn net xietansheng article details 72814531 Java Swing GUI 图形界面窗口开发基础教程 xff0c 本教程将系统性地详细介绍 Java Swing 开

随机推荐