携手创作,共同成长!这是我参与「掘金日新计划 · 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,解法类似,所以放在同一篇,都是使用了贪心算法,每一次跳跃总是做出当前看来最好的选择,即在解决问题的时候,问题的最优解可以通过局部最优的选择得到
- 在日常的问题中,能真正适用贪心算法的很少,因为不能求一些最值的问题,或者是求一个范围的答案
- 今天也是有收获的一天