一起刷LeetCode——跳跃游戏(贪心算法)

45 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

跳跃游戏

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。

(I)判断你是否能够到达最后一个下标。

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ju…

分析

  • 在每次跳之前都先计算一下到目前为止能跳多远,计算出最大值之后,检查当前的最大值是否大于等于目标值,问题就可以迎刃而解了
  • 优化:在判断能否到达最后一个下标的时候,如果数组的某个下标就已经不能到达,那么就可以提前终止对nums的遍历;如果在遍历几个下标的时候就能判断可以到达最后一个下标,同样也可以提前终止
代码
var canJump = function(nums){
    let idx = 0
    let max = 0
    let target = nums.length - 1
    while(idx<nums.length){
        max = Math.max(max, idx+nums[idx]
        if(max >= target){
            return true
        }
        if(max <= idx && nums[idx]===0){
            return false
        }
        idx++
    }
    return false
}

(II)你的目标是使用最少的跳跃次数到达数组的最后一个位置。(假设你总是可以到达数组的最后一个位置。)

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ju…

分析

  • 给出的数组是在当前位置能跳的最大长度,所以在位置i的时候,下一步的长度区间是i-i+nums[i],一旦下一步的长度可以到最后一个位置,那就找到了答案
代码
var jump = function(nums){
    let maxReach = 0
    let end = 0
    let jump = 0
    for(let i =0;i<nums.length - 1;i++){
        maxReach = Math.max(maxReach, i+nums[i])
        if(i === end){
            jump ++
            end = maxReach
        }
    }
    return jump
}

总结

  • 今天两道题均为跳跃游戏,分别是I和II,解法类似,所以放在同一篇,都是使用了贪心算法,每一次跳跃总是做出当前看来最好的选择,即在解决问题的时候,问题的最优解可以通过局部最优的选择得到
  • 在日常的问题中,能真正适用贪心算法的很少,因为不能求一些最值的问题,或者是求一个范围的答案
  • 今天也是有收获的一天