45.跳跃游戏II
题面:
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
示例:
输入: [ 2 , 3 , 1 , 1 , 4 ] [2,3,1,1,4] [2,3,1,1,4]
输出: 2 2 2
解释: 跳到最后一个位置的最小跳跃数是 2 2 2。从下标为 0 0 0 跳到下标为 1 1 1 的位置,跳 1 1 1 步,然后跳 3 3 3 步到达数组的最后一个位置。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game-ii
分析:
一道自底向上的贪心题。通过每个局部都取最优解来达到全局最优的效果。
如果想要知道最短的跳跃次数,那么每一步都应该需要跳到这一步能达到的最远的距离。
根据题意,数组中所有的元素都应该被访问。因此设置一根从前到后依次遍历的指针,访问数组中的所有元素。假设当前站在 $pos $ 的位置上,则下一步最远能够跳到
p
o
s
+
n
u
m
s
[
p
o
s
]
pos + nums[pos]
pos+nums[pos] 。在访问到当前一步的最远区间
t
a
r
g
e
t
target
target之前,不断地更新下一步能达到的最远距离
c
u
r
M
a
x
P
o
s
curMaxPos
curMaxPos。访问到
t
a
r
g
e
t
target
target后,更新新的
t
a
r
g
e
t
target
target值为
c
u
r
M
a
x
P
o
s
curMaxPos
curMaxPos,步数的计数器
s
t
e
p
step
step自增,直到指针碰到最后一个数为止。这样就能够保证每一步的终点都是这一步能够去到的最远范围,通过局部最优解得到全局最优解。
代码:
class Solution {
public:
int jump(vector<int>& nums) {
int curMaxPos = 0;
int step = 0;
int target = 0;
for (int i=0;i<nums.size()-1;i++)//不要包含终点,否则可能多跳一步
{
curMaxPos = max(curMaxPos, i+nums[i]);
//贪心,用这一步的最大解和现在已经能访问的区间比较
if (i == target)//若已到达上一步可以访问的最大值
{//则更新下一个目标为当前这步能走到的最大值
target = curMaxPos;
step++;
}
}
return step;
}
};