贪心—跳跃游戏
题目要求:
给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false
这是一道经典的贪心算法题目,核心思路是:维护当前能到达的最远位置,遍历数组时不断更新这个最远位置,如果遍历过程中当前位置超过了最远位置,说明无法到达终点;如果最远位置能覆盖最后一个下标,就返回 true。
代码解释
- 变量定义:maxReach 表示当前能跳跃到的最远下标,初始值为 0(起点)。
- 遍历数组:
- 第一个判断:如果当前遍历的位置 i 超过了 maxReach,说明这个位置根本到不了,直接返回 false。
- 更新最远位置:i + nums[i] 是从当前位置能跳到的最远下标,和原 maxReach 比较,保留更大的值。
- 提前终止:如果 maxReach 已经大于等于最后一个下标,直接返回 true,无需继续遍历。
- 最终返回:遍历完成后,说明全程都能到达,返回 true。
注意
- 首先在循环中引入if判断当前位置i能否到达,
if(i<maxReach){ //最远到达位置初始化为0 int maxReach = 0;
return false;
}
-
若当前位置可以到达,即(maxReach>=i),再更新当前位置能到达的最远位置,
maxReach = Math.max(maxReach,i+num[i]); -
如果当前位置能到达的最远位置覆盖了终点,则无需再往后遍历
if(maxReach >= nums.length -1){
return true;
}
- 循环遍历完都没有返回false,说明遍历的每一个位置都是可以到达的,终点亦然。
return true
Java代码实现如下:
public class JumpGame {
public boolean canJump(int[] nums) {
// 记录当前能到达的最远位置
int maxReach = 0;
// 遍历数组(注意:不需要遍历到最后一个元素,因为到达即可)
for (int i = 0; i < nums.length; i++) {
// 如果当前位置已经超过了能到达的最远位置,直接返回false
if (i > maxReach) {
return false;
}
// 更新最远能到达的位置:当前位置+可跳跃长度 和 原最远位置 取最大值
maxReach = Math.max(maxReach, i + nums[i]);
// 优化:如果最远位置已经覆盖最后一个下标,提前返回true
if (maxReach >= nums.length - 1) {
return true;
}
}
// 遍历结束,说明能到达终点
return true;
}
// 测试示例
public static void main(String[] args) {
JumpGame solution = new JumpGame();
// 示例1:能到达 [2,3,1,1,4] → true
int[] nums1 = {2, 3, 1, 1, 4};
System.out.println(solution.canJump(nums1));
// 示例2:不能到达 [3,2,1,0,4] → false
int[] nums2 = {3, 2, 1, 0, 4};
System.out.println(solution.canJump(nums2));
}
}
算法复杂度
- 时间复杂度:O (n),只需要遍历一次数组。
- 空间复杂度:O (1),只使用了常数个额外变量。
总结
- 核心思想:贪心算法,每一步都取能跳跃的最远位置;
- 关键判断:当前位置是否超出最远可达位置、最远位置是否覆盖终点;
- 最优解:时间 / 空间复杂度都是最优,无冗余计算。
浙公网安备 33010602011771号