思路一:
题目描述
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
示例 2:
输入: nums = [2,3,0,1,4]
输出: 2
思路分析
贪心,每次都找最优的那个操作。
读取当前所指的值,看看后面跳跃的范围中那个最大。选择最大的跳。
找了张图 ,帮助理解。
- 显然开始的时候在0位置,可跳跃范围是 1,2号位置。1号位的数最大,所以跳到一号位。
- 然后到了1号位,1号位为3.可以跳跃到最后一个4号位。所以此时程序结束。跳了两次。别忘了最后一次也要跳。
完整代码:
class Solution:
def jump(self, nums: List[int]) -> int:
# 如果起点就是终点
if len(nums) == 1:
return 0
# 如果一步就能跳到终点
if nums[0] >= len(nums)-1:
return 1
max_pos = 0 # 最远位置
count = 1 # 跳跃次数 (默认第一步能跳出去且未到达终点)
cur = 0 # 当前位置
while True:
# 遍历从当前位置可以跳到所有位置
for i in range(cur + 1, cur + nums[cur] + 1):
# 如果已经能跳到终点就不再继续了
if i + nums[i] >= len(nums) - 1:
return count + 1 # 出口在这里
# 选取能跳的最远的下一个位置
if i + nums[i] > max_pos:
cur = i # 更新位置
max_pos = i + nums[i] # 更新距离
count += 1 # 更新跳跃计数
思路二:
题目已经说明,必然能达到最后一个位置,并且要求使用最少的步数。
那么每次跳跃的时候,在可跳跃范围内选择下一次跳跃的起点,使得本次跳跃+下次跳跃可以达到的距离最远。
使用一趟遍历完成操作:
设置记录答案最少步数的变量 res, 下一次跳跃的最远距离 max_pos, 本次跳跃的最远距离 end。
何时让步数+1?
显然,当前遍历下标i到了本次跳跃的最远距离end时,步数+1。
流程:
- 初始化 end = 0 ,本次和下次跳跃最远距离都是0.
- 遍历数组,不断更新下次跳跃最远的距离。
- 若当前遍历下标i已经达到了本次跳跃的最远距离end,则让步数res+1,然后将记录的下次跳跃最远距离max_pos 更新 ,变成这次跳跃的最远距离end。
- 不断重复上述过程
实际上简单来讲,就是 不断循环数组,从遍历下标i到end,在此过程中找出下次跳跃的最远距离,如果遍历下标到达本次的边界end了,则说明本次遍历已经完事了,已经达到本次的最远距离了,步数+1.然后让刚才找到的下次跳跃最远距离变成本次的,然后重复操作就行了。
这里有个细节就是循环到 倒数第二个值(含),不遍历最后一个值。
这块可以想象一下,我们操作的时候是 当 i == end时步数+1,也就是说当前下标i已经走到了边界了,该下一步了,所以直接让步数+1了。
如果遍历是到最后一个值,恰好end也是最后一个值,那就 i == end 步数加1了。显然最大跳跃距离到最后一个值的时候程序结束了,不需要步数再+1了。
class Solution:
def jump(self, nums: List[int]) -> int:
end = 0
res = 0
max_pos = 0
for i in range(len(nums)-1): # 遍历到倒数第二个值(含)
max_pos = max(max_pos,nums[i]+i) # 从i到当前跳跃最大距离end中,不断寻找下一次能跳出的最远距离
if i == end: # 已经走到了本次跳跃的最远距离,步数+1,该跳下一次了,更新最远的跳跃距离。
end = max_pos
res +=1
return res