给定一个非负整数数组,最初位于数组的第一个位置。数组中的每个元素代表在该位置可以跳跃的最大长度。判断是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
示例 2:
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
package com.loo;
public class JumpGame {
/**
* @param args
*/
public static void main(String[] args) {
int[] arr1 = new int[]{2, 3, 1, 0, 4};
int[] arr2 = new int[]{3, 2, 1, 0, 4};
int[] arr3 = new int[]{0}; // 开始位置就是自己所在的位置,可达
System.out.println(canJumpGame1(arr3));
System.out.println(canJumpGame2(arr2));
System.out.println(canJumpGame3(arr1));
}
// 如果最远可以到达的位置大于等于数组中的最后一个位置,那就说明最后一个位置可达,反之,如果在遍历结束后,最后一个位置仍然不可达
public static boolean canJumpGame1(int[] arr) {
if (arr == null || arr.length == 0) {
return false;
}
int len = arr.length;
int jumpRight = 0;
for (int i=0;i<len;i++) {
if (i<=jumpRight) {
jumpRight = Math.max(jumpRight, i + arr[i]);
if (jumpRight >= len-1) {
return true;
}
}
}
return false;
}
// 记录一个能够到达最后位置的下标,并初始化为数组的最大下标;
// 每次移动这个下标的位置,从后往前走;
// 如果某个位置最多能跳的距离大于或者等于最后的一个能够跳到最终点的下标(之前记录的),说明该位置是能够跳到最后点的,更新到之前记录的下标;
// 最后判断之前记录的下标是否为 0 ,为 0 代表第一个坐标位置也能够跳到最后。
public static boolean canJumpGame2(int[] arr) {
if (arr == null || arr.length == 0) {
return false;
}
int jumpIndex = arr.length - 1;
for (int i=jumpIndex;i>=0;i--) {
if (i + arr[i]>=jumpIndex) {
jumpIndex = i;
}
}
return jumpIndex == 0;
}
// 从后往前遍历,判断当前位置的元素endIndex,是否能被之前的元素startIndex跳跃到;跳跃到则更新endIndex = startIndex;
// 继续对新的endIndex元素进行判断,直到到达数组第一个元素。
public static boolean canJumpGame3(int[] arr) {
if (arr == null || arr.length == 0) {
return false;
}
int endIndex = arr.length - 1;
int startIndex = endIndex - 1;
while (startIndex >= 0) {
System.out.println("startIndex:" + startIndex + ",arr[" + startIndex + "]:" + arr[startIndex] + ",endIndex:" + endIndex);
if (startIndex + arr[startIndex] >= endIndex) {
endIndex = startIndex;
startIndex = endIndex - 1;
} else if (--startIndex == -1) {
return false;
}
}
return true;
}
}