给定一个长度为 n
的 0 索引整数数组 nums
。初始位置为 nums[0]
。
每个元素 nums[i]
表示从索引 i
向前跳转的最大长度。换句话说,如果你在 nums[i]
处,你可以跳转到任意 nums[i + j]
处:
0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1]
的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]
。
示例 1:
输入: nums = [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是2
。 从下标为 0 跳到下标为 1 的位置,跳1
步,然后跳3
步到达数组的最后一个位置。
示例 2:
输入: nums = [2,3,0,1,4] 输出: 2
提示:
1 <= nums.length <= 104
0 <= nums[i] <= 1000
- 题目保证可以到达
nums[n-1]
源码如下:
class Solution {
public:
int jump(vector<int>& nums) {
int n = nums.size(); // 数组的大小
int rightmost = 0; // 当前能跳到的最远位置
int ans = 0; // 跳跃的次数
int end = 0; // 当前跳跃的边界
for (int i = 0; i < n - 1; i++) { // 遍历数组,不包括最后一个元素
if (i <= rightmost) { // 如果当前位置可以到达
rightmost = max(rightmost, i + nums[i]); // 更新能跳到的最远位置
if (i == end) { // 如果当前位置达到了边界
end = rightmost; // 更新边界为能跳到的最远位置
ans++; // 跳跃次数加1
}
}
}
return ans; // 返回最小的跳跃次数
}
};
代码中使用了贪心算法的思想。该算法每次都选择能跳跃到的最远位置,直到达到数组的最后一个位置。
代码解析如下:
-
初始化变量:
- n:数组的大小
- rightmost:当前能跳到的最远位置。这个变量初始值为0,表示起始位置。在遍历数组过程中,该变量会不断更新为能跳到的最远位置。
- ans:跳跃的次数。初始值为0。
- end:当前跳跃的边界。初始值为0。在遍历数组过程中,如果当前位置达到了边界,说明需要进行一次新的跳跃,此时边界需要更新为能跳到的最远位置,并且跳跃次数加1。
-
遍历数组:
- 对于每个位置i,判断是否能到达:
- 如果i小于等于rightmost,表示当前位置可以到达:
- 更新能跳到的最远位置:rightmost = max(rightmost, i + nums[i])
- 如果当前位置达到了边界:i == end,表示需要进行一次新的跳跃:
- 更新边界为能跳到的最远位置:end = rightmost
- 跳跃次数加1:ans++
-
返回最小的跳跃次数:ans
总结:该算法通过遍历数组,不断更新能跳到的最远位置和当前跳跃的边界,从而求解最小的跳跃次数。算法的时间复杂度为O(n),其中n为数组的大小。
注意这里的i在循环里面是小于n-1而不是n,这是因为我们不需要考虑最后一个数的跳跃问题。