LeetCode 55.跳跃游戏

200 阅读1分钟

「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」。

题目:给定一个非负整数数组,最开始位于数组的第一个元素,可以根据数组元素选择跳跃的长度,长度最大为当前位置的数组值,判断当前数组能否根据此规则到达数组的最后一个下标。

解题思路

根据数据的下标游走,只需从数组首元素开始记录,记录每个元素所能到达的最远距离,之后判断最远距离是否大于或者等于最后一个元素的下标,如果大于则代表可以跳过去,此时退出程序,可以减少循环。如果最远距离小于等于当前元素下标则表示不能跳过去,则直接返回false。代码如下:

public boolean canJump(int[] nums) {
        int step=0;
        for(int i=0;i<nums.length;i++){
            if(i>step) return false;
            step = Math.max(step, i+nums[i]);
            if(step>=nums.length-1) return true;
        }
        return true;
    }

最终耗时2ms,上述代码的时间复杂度为O(N)O(N),空间复杂度为O(1)O(1),对于for循环还可以进一步优化,在遍历时可以维护当前最远可到达的距离,此时可以将for循环改为:

for(int i=0;i<=step;i++)

思路二

上述方法是从前往后来计算最远距离判断是否可以到达最后一个位置,那么是否可以从后往前来判断呢?实际上是可以的,思路如下:

我们可以从后往前遍历,每次遍历计算当前元素是否能到达终点,此处的终点初始化为数组的最后一个位置,在往前遍历过程中,如果判断当前位置所在点可以到达终点,则更新终点,将当前位置作为下一次遍历的终点,不断更新终点的位置,最后如果可以到达最后一个位置,那么最终终点必然0,否则则为不能。代码如下:

public boolean canJump(int[] nums) {
    int end = nums.length-1;
    for(int i=end;i>=0;i--){
        if(nums[i] + i >= end){
            end = i;
        }
    }
    return end==0;
}

上述代码实际耗时1ms,击败百分百Java用户,时间复杂度为O(N)O(N),空间复杂度为O(1)O(1)