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 , 所以永远不可能到达最后一个下标。

思路分析

贪心思路:

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

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

leetcode(力扣) 55. 跳跃游戏 (贪心 & 动态规划)_第1张图片

举例:

若所给数组为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
        



你可能感兴趣的:(个人笔记,交流学习,leetcode,python)