45. 跳跃游戏 II
✨核心逻辑
本题采用 贪心算法 的策略,在遍历过程中维护当前能跳到的最远位置:
- 维护边界与最远距离:使用
end记录当前这一步跳跃能够覆盖的边界下标,使用maxValue记录在遍历过程中能到达的最远下标。 - 单步贪心:在到达当前跳跃的边界
end之前,不断计算从当前位置出发能够跳到的最远距离,并更新maxValue。 - 跨越边界:当指针
i走到边界end时,说明当前这一步的最优最远距离已经确定,我们必须在这里进行下一次跳跃(跳跃次数加 1),并把边界end更新为之前计算出的最远距离maxValue。 - 逐步推进:只要边界还没覆盖到数组末尾,就继续重复上述过程,最终得到的最小跳跃次数即为答案。
🔥代码实现(含详细变量注释)
class Solution {
public int jump(int[] nums) {
// maxValue:记录在已经遍历的范围内,当前能够到达的最远下标位置
int maxValue = 0;
// n:记录给定数组的长度
int n = nums.length;
// jump:记录到达终点所需的当前最小跳跃次数
int jump = 0;
// i:用于遍历数组的索引指针,从前向后扫描
int i = 0;
// end:记录当前这一次跳跃所能覆盖的最远边界下标(本次跳跃可达的边界)
int end = 0;
// 边界情况:如果数组长度小于等于1,说明最开始就在最后一个下标,不需要跳跃,直接返回 0
if (n <= 1) {
return 0;
}
// 只要当前跳跃的边界 end 还没有到达数组的最后一个下标 n-1,说明还没到终点,继续计算
while (end < n - 1) {
// 贪心表达式:计算从当前位置 i 出发,能够跳到的最远距离 `i + nums[i]`
// 并与当前记录的全局最远距离 maxValue 比较,保存最大值
maxValue = Math.max(maxValue, i + nums[i]);
// 当遍历指针 i 走过了当前跳跃范围所覆盖的全部区域(到达边界)时
if (i == end) {
// 必须起跳,因此跳跃次数累加 1
jump++;
// 以本次遍历中统计出的全局最远距离 maxValue,作为下一步跳跃的新边界
end = maxValue;
}
// 指针 i 加 1,继续遍历下一个元素
i++;
}
// 当 while 循环结束时,说明已经跳到了终点,返回统计的最小跳跃次数
return jump;
}
}
- ⏱️复杂度分析
时间复杂度:O(N),其中 N 是数组的长度。我们只需要对数组进行一次遍历,在循环内部执行常数次操作。
空间复杂度:O(1),只使用了 maxValue、n、jump、i、end 几个额外的整型变量,没有占用额外的数组空间。