LeetCode 55. 跳跃游戏

LeetCode 55. 跳跃游戏

给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
提示:
1 <= nums.length <= 104
0 <= nums[i] <= 105

贪心

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        pos = 0
        for idx, num in enumerate(nums):
            if idx > pos or pos >= len(nums) - 1:
                break
            pos = max(pos, idx + num)
        return pos >= len(nums) - 1

虽然enumerate更加pythonic,但是实际测试enrmerate相比range更加耗时,不过差的很少,大概10ms左右,不影响AC

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        l = len(nums)
        pos = 0
        for idx in range(l):
            if idx > pos or pos >= l - 1:
                break
            pos = max(pos, idx + nums[idx])
        return pos >= l - 1

写复杂了…

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # 从第一个位置往后走,记为p, p == end2,跳跃行动,直到到达目的地或者跳不动,记为end1,跳不动就回返,直到这一系列起跳的位置end2,然后得出最多能比最大记录往前跳几步step
        # 获得新的起跳点p = end1 + step,step == 0,表示导不了目的地,否则继续跳跃行动,直到到达目的地或者跳不动,记为end2,回返,直到上一次行动的结束位置end1
        # 重复上述过程必然可以获得最终结果
        target = len(nums) - 1
        p = end2 = 0
        while p < target:
            if nums[p]:
                p += nums[p]
            else:
                end1 = p
                step = 0
                while p > end2:
                    step = max(step, p + nums[p] - end1)
                    p -= 1
                if step == 0:
                    return False
                else:
                    p = end1 + step
                    end1, end2 = end2, end1
        return True

动态规划

看了一眼评论区,有人指出贪心实质上是动态规划,动态规划的思路如下,dp[n]为0~n位置能跳到的最远距离,所以状态转移方程为dp[n] = max(dp[n-1], dp[n-1] + nums[n]),初始值可以设置dp[0] = nums[0],一维动态规划,同时根据状态转移方程可知只涉及n和n-1,可以进行滚动优化,使用一个变量即可替代整个dp数组,由此可得解法。实质上滚动优化后动态规划思路的代码和贪心思路的代码是一致的。
果然动态规划最难的是找状态。

2024.10.01写的动态规划,没过,然后搜到了这篇文章…这次的dp不如上面的思路

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # dp[i] 表示能否从最开始跳到 i
        # dp[i] = dp[i- nums[j]] | dp[i- (nums[j] - 1)] | ... | dp[i]
        dp = [False] * len(nums)
        dp[0] = True
        for i in range(1, len(nums)):
            for j in range(0, i):
                if dp[j]:
                    dp[i] |= j + nums[j] >= i
        return dp[-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值