【解题思路】
「贪心」地进行正向查找,每次找到可到达的最远位置,就可以在线性时间内得到最少的跳跃次数。
例如,对于数组 [2,3,1,2,4,2,3],初始位置是下标 0,从下标 0 出发,最远可到达下标 2。下标 0 可到达的位置中,下标 1 的值是 3,从下标 1 出发可以达到更远的位置,因此第一步到达下标 1。
从下标 1 出发,最远可到达下标 4。下标 1 可到达的位置中,下标 4 的值是 4 ,从下标 4 出发可以达到更远的位置,因此第二步到达下标 4。
在具体的实现中,我们维护当前能够到达的最大下标位置,记为边界。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1。
在遍历数组时,我们不访问最后一个元素,这是因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。
基于上述官方解答,以下为自己理解:
1. 每一次跳跃时更新能到达的最远距离;
2. 当前索引与边界相等时,才会必须跳跃一次;【跳跃点和维护的边界点(记录跳跃次数的点)并不一致,但是两者的总次数是相等的】
下图中红框中为 “维护的边界点”,蓝筐中对应的为 “跳跃点”。
(1) index=0时,跳跃的最远距离为index=2,此为边界点;到达的index=1,2。index=1,2没有到达最终点,所以必须得跳一次。当index=2时,即到达了第一次index=0跳跃时的边界点,这时已经统计出了index=1时跳的最远,最远可以跳到index=4。
(2) index=1,2时,跳跃的最远距离为index=4,此为边界点;到达的index=2,3,4。
(3) index=2,3,4时,跳跃的最远距离为index=4+4;到达的index=5,6。
class Solution:
def jump(self, nums: List[int]) -> int:
steps = 0
max_distance = 0
end_distance = 0
for i in range(len(nums)-1):
max_distance = max(max_distance, nums[i]+i)
if i == end_distance:
end_distance = max_distance
steps += 1
return steps