18.跳跃游戏(medium)

1.题目链接

55. 跳跃游戏 - 力扣(LeetCode)55. 跳跃游戏 - 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 1:输入:nums = [2,3,1,1,4]输出:true解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。示例 2:输入:nums = [3,2,1,0,4]输出:false解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。 提示: * 1 <= nums.length <= 104 * 0 <= nums[i] <= 105https://leetcode.cn/problems/jump-game/description/2.题目描述

给你一个非负整数数组 nums  ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位   置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true  ;否则,返回 false  。​
 ​
示例 1:​
输入:nums = [2,3,1,1,4]​
输出:true​
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。​示例 2:​
输入:nums = [3,2,1,0,4]​
输出:false​
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

 提示:

1 <= nums.length <= 10(4)

0 <= nums[i] <= 10(5)

3. 解法:
和 跳跃游戏II 一样,仅需修改一下返回值即可。​

Java算法代码:

class Solution {
    public boolean canJump(int[] nums) {
        int left = 0, right = 0, maxPos = 0, n = nums.length;
        while(left <= right){
            if(maxPos >= n - 1){
                return true;
            }
            for(int i = left; i <= right; i++){
                maxPos = Math.max(maxPos, nums[i] + i);
            }
            left = right + 1;
            right = maxPos;
        }
        return false;
    }
}

运行结果:

贪心策略:

新思路分析

a. 思路描述
  • 观察:由于数组元素是非负整数(nums[i] >= 0),跳跃距离至少为 0。
  • 关键点
    1. 如果数组中没有 0,则每个位置都能跳跃至少 1 步(nums[i] >= 1),可以逐步前进到最后一个位置,返回 true。
    2. 如果数组中有 0,则 0 是一个“障碍”,因为到达 0 的位置后无法继续跳跃。
    3. 对于每个 0,判断是否能从 0 前面的某个位置跳到 0 后面的位置(即“越过” 0)。
    4. 对所有 0 进行判断,如果都能越过,则可以到达终点。
b. 思路可行性
  • 正确性分析
    • 没有 0 的情况:如果 nums[i] >= 1 恒成立,则可以从索引 0 逐步跳到 n-1,每次至少跳 1 步。这种情况确实总是返回 true。
    • 有 0 的情况:0 会阻断路径。例如 [3,2,1,0,4] 中,索引 3 的值为 0,到达后无法继续。需要检查是否能从索引 0、1 或 2 跳到索引 4(即 nums[i] + i >= 4)。
    • 越过 0:对于每个 0 的位置 k,需要找到一个位置 i < k,使得 nums[i] + i > k。
    • 所有 0 都可越过:如果每个 0 都能被越过,则路径不会中断,最终可以到达 n-1。
  • 边界情况
    • 如果 n == 1,无需跳跃,直接可达。
    • 如果最后一个位置是 0(nums[n-1] == 0),需要到达 n-1,无需继续跳跃。
  • 结论:思路是可行的,且符合题目要求。
c. 与贪心策略的关系
  • 思路实际上是贪心策略的一种变体:
    • 贪心策略的核心是维护一个最远可达位置 maxPos,逐步扩展。
    • 新方法关注“障碍”(0),通过检查是否能越过每个 0,隐式地实现了相同的覆盖检查。
  • 两者的等价性:如果某个 0 无法越过,等价于贪心策略中的 maxPos 无法覆盖 n-1。

Java算法代码:

class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length;
        // 打印输入数组
        System.out.println("Input array: " + Arrays.toString(nums));
        
        // 边界情况:长度为 1,直接可达
        if (n == 1) {
            System.out.println("Array length is 1, directly reachable");
            return true;
        }

        // 检查是否有 0
        boolean hasZero = false;
        for (int i = 0; i < n; i++) {
            if (nums[i] == 0) {
                hasZero = true;
                break;
            }
        }
        System.out.println("Has zero in array: " + hasZero);

        // 如果没有 0,则一定可达
        if (!hasZero) {
            System.out.println("No zeros found, can reach the end");
            return true;
        }

        // 检查每个 0 是否能被越过
        for (int k = 0; k < n; k++) {
            if (nums[k] != 0) continue; // 跳过非 0 位置
            System.out.println("Found zero at position k=" + k);
            
            // 如果 0 是最后一个位置,只需到达即可
            if (k == n - 1) {
                System.out.println("Zero is at the last position, check if reachable");
                continue;
            }

            // 检查是否存在 i < k,使得 nums[i] + i > k
            boolean canCross = false;
            for (int i = 0; i < k; i++) {
                int jumpDistance = nums[i] + i;
                System.out.println("  Checking position i=" + i + ": nums[i]=" + nums[i] + ", can jump to " + jumpDistance);
                if (jumpDistance > k) {
                    canCross = true;
                    System.out.println("  Can cross zero at k=" + k + " from i=" + i);
                    break;
                }
            }

            // 如果无法越过这个 0,则无法到达
            if (!canCross) {
                System.out.println("Cannot cross zero at position k=" + k + ", cannot reach the end");
                return false;
            }
        }

        // 如果所有 0 都能越过,则可达
        System.out.println("All zeros can be crossed, can reach the end");
        return true;
    }
}

分析:这里可以发现,这里就是分别进行判断(注释中该写的都写了)

长度为1,直接可以到达。和0无关。

如果没有0,可以到达,直接true。

如果有0,通过循环找零。从第一个找到的0开始处理。看前面的 i + nums[i]能不能越过0,如果能越过,继续找下一个。不能就false。不断循环。直到所有的0都能跳过,那么就是true'。

只要有一个不能就是false。

Input array: [3, 2, 1, 0, 4] Has zero in array: true Found zero at position k=3 Checking position i=0: nums[i]=3, can jump to 3 Checking position i=1: nums[i]=2, can jump to 3 Checking position i=2: nums[i]=1, can jump to 3 Cannot cross zero at position k=3, cannot reach the end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值