LeetCode 45. 跳跃游戏 II

题目说明

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例 :
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

来源:力扣(LeetCode)
题目链接

难度:困难

本题参考了官方题解的思路。

方法一:贪心算法(双向遍历)

第一个指针index指向最后一个节点,然后利用贪心的思路,每次从左向右寻找离它最远的可达点。然后index设置为该点,继续重复操作。以此类推,直到index指向数组开始位置。

那么为什么要用离它最远的可达点?
我们可以假设对于num[index]点,在它左边存在n个点可以一步到达num[index],其中离它最远的点取名为num[far],最近的点取名为num[near]。
那么对于这n个点来说,在num[far - i]的集合中,能一步到达num[near]的点,一定也能一步到达其他n - 1个点。反之能一步到达num[far]的点,却不一定能一步到达其他n - 1个点。
如果我们给到达这n个点之前走过的步数取名为steps的话,那么steps[far] 一定小于等于其他的steps。所以要取最远的可达点。

时间复杂度:最佳O(n),最差O(n^2)

class Solution {
    public int jump(int[] nums) {
        int index = nums.length - 1;
        int min = 0;
        while(index > 0){
            int i = 0;
            for(; i < index; i++){
                if(nums[i] >= index - i){
                    break;
                }
            }
            min ++;
            index = i;
        }
        return min;
    }
}

方法二:贪心算法(正序遍历一次)

可以正序遍历一次求解这个问题。
在遍历的过程中,计算 i 到 next之间所有点自身的最远可达距离中的最大值,作为下一段遍历区间的结束位置next,每段遍历结束时步数 + 1。直到遍历到数组尽头。

为什么选取 i 到 next之间所有点最远可达距离中的最大值?
个人比较通俗的理解:贪心贪的是i+nums[i],每次选择i 到 next之间i+nums[i]最大的,也就是选择了一个相同步数下接下来范围最大的解,涵盖了其他点的选择范围。就算nums[maxPos]这个点的值是0, 我把这个最大范围减1也大于等于其他的可能范围。即从其它点出发能到达的范围,如果超过了最佳点的索引值,在相同的步数下这个最佳点一定也能到达;如果没超过最佳点的索引值,那还要额外的步数才能到最佳点呢。

时间复杂度:O(n)

class Solution {
    public int jump(int[] nums) {
        int maxPos = 0;
        int i = 0;
        int steps = 0;
        int next = 0;
        while(next < nums.length - 1){
            maxPos = Math.max(maxPos, i + nums[i]);
            if(next == i){
                next = maxPos;
                steps ++;
            }
            i ++;
        }
        return steps;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值