leetcode(力扣) 55. 跳跃游戏 (贪心 & 动态规划)

题目描述

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

示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

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

思路分析

贪心思路:

贪心思路比较好理解,我们并不需要关注某一个格子到底需要跳几格,只要每次都找到当前下标可以达到最远距离,判断这个最远距离是不是能达到数组的最后就行了。

我偷了个图,看了就明白了。

在这里插入图片描述

举例:

若所给数组为nums = [2,3,1,4,6,7] 遍历到2的时候,最远距离可以到1,而遍历到3的时候,最远距离可以到 3所在的下标 +当前下标可以跳跃的最远举例,即
1+nums[1] = 4

另一种情况就是 nums = [6,2,1,4,6,7] ,此时遍历到2 的时候,最远距离可以到 1+2 = 3,但是前一个数是6,所以最远距离并没有变。

由此推导代码: 最远距离 设为 max_index 。
则:max_index = max(i+nums[i],max_index)

动态规划思路:

其实和贪心思路差不多。

老规矩 五步走:

1.确定dp数组含义:
dp[i] 表示从下标i起跳可以调到的最远距离。

2.状态转移公式:

跟贪心思路一样,两种情况:有可能当前nums[i] 所表示的距离是新的最大距离,也有可能之前的值是最大距离,比如 [1,4] 遍历到4就是新的最大距离,而[6,1],即使遍历到了1,最大距离也在是的6。

在看一下dp含义,dp[i] 表示下标i可以到达的最远距离。
所以,如果是[6,1]这种情况,当下标遍历到1,此时最远距离是 在上一时刻也就是遍历到6的那个时刻的最远距离减一,因为从6走到了1嘛。

故:
dp[i] = max(dp[i-1]-1,nums[i])

3.初始化dp数组:
dp[i]依赖于dp[i-1],所以第一个值需要初始化。
回顾dp含义 dp[i] 表示下标i可以到达的最远距离。
显然:dp[0] = nums[0]

4.遍历顺序:
没得说,从前往后。

5.返回值:

这里其实有一点细节,就是如果dp[i-1] = 0 那么就意味着从i-1下标处可以移动的最远距离为0,也就是无法向前移动了,自然也无法达到i,更无法达到数组末尾了。此时直接返回False即可。

遍历到最后return True

根据dp公式 : dp[i] = max(dp[i-1]-1,nums[i])
当前值只依赖于前一个值和已给的nums数组,所以只需要维护两个值就行了,可以用状态压缩优化一下代码。

不看公式也比较好想,比如[2,6,1] 实际上6已经考虑了前面的2了,到6这里最大距离更新为6,所以1也只需要考虑自己和前一个的最大距离,[10,6,1]也是这样,遍历到6的时候,6考虑了前面的10,最大距离没更新。所以一直都是每一个状态只需要考虑自己和前一个状态。

完整代码

贪心:
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        max_index = 0
        for i in range(len(nums)):
            # 之前可达最远处和最新的可达最远处
            max_index = max(i + nums[i],max_index)
            if max_index >= len(nums)-1:
                return True
            if max_index-1 < i :
                return False
        
动态规划:
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # dp[i] 表示在下标i处可以达到的最远距离。
        dp = [0] * len(nums)
        dp[0] = nums[0]
        for i in range(1,len(nums)):
            dp[i] = max(dp[i-1]-1,nums[i])
            if dp[i-1] == 0:
                return False
            
        return True
        



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不学习!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值