LeetCode 45.跳跃游戏② (超详细)

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

示例 1:

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

输入: nums = [2,3,0,1,4]
输出: 2
 

提示:

1 <= nums.length <= 104
0 <= nums[i] <= 1000

思路:本题对于55题难度增加了不少,但是思路是相似的,都是要看最大覆盖范围。

55题链接LeetCode 55跳跃游戏_小犹太*的博客-CSDN博客给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标。示例 1:输入:nums = [2,3,1,1,4]输出:true解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。示例2:输入:nums = [3,2,1,0,4]输出:false解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最.https://blog.csdn.net/wxxrqq/article/details/123762877

本题要计算最少步数那么就要想清楚什么情况下步数必须加一

局部最优:在当前可移动距离固定时,尽可能多走,如果还没到终点,则步数加一。

整体最优:用最小步数到达终点。

虽然思路是这样的但是写代码的时候还步数想跳多远就跳多远这样就不知道下一步最远能到达哪里了。

所以真正题解的时候,要从覆盖范围出发,不管怎么跳覆盖范围内是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦到达终点,得到的就是最小步数。


  • 当移动下标达到最远距离时,步数就要加一来增加覆盖距离,最后的步数就是最小步数
  • 这里还 有两种情况需要考虑,当移动下标达到了当前覆盖最远距离下标时:
  1. 如果当前覆盖范围的最远距离的下标不是集合终点,那么步数加一还要继续移动。
  2. 如果当前覆盖范围的最远距离的下标就是集合终点,那么步数就不用加一,因为不用再往后移动了。

解法一:

  1. class Solution {
        public int jump(int[] nums) {
        	int ans =0;//记录步数
        	int cur =0;//当前覆盖的最远距离下标
        	int next =0;//下一步覆盖的最远距离下标
        	for(int i=0;i<nums.length;i++) {
            //   更新下一步最远距离下标
        		next = Math.max(next, i+nums[i]);
                //遇到当前覆盖最远距离下标
        		if (i==cur) {
                //如果当前覆盖最远距离下标不是终点
    				if(cur!=nums.length-1) {
    					cur =next;//更新当前覆盖最远距离下标
    					ans++;//需要走下一步
    					if (next>=nums.length-1) {//下一步的覆盖范围已经包括终点,结束循环
    						break;
    					}
    				}else break;//当前覆盖最远下标是终点,不需要再走
    			}
        	}
        	return ans;
        }
    }

    针对解法一的情况,可以统一处理,既移动下标只要遇到当前最远覆盖距离的下标,步数加一,不需要考虑是不是终点的问题。

想要达到这样的效果只需要让移动下标的最远只能移动到下标为nums()-2的地方即可,以为当移动下标指向nums()-2时:

  •         如果移动下标等于当前覆盖的最远距离的下标,则需要再走一步,最后一步无论如何都可以走到终点。
  • 如果移动下标不等于当前最远覆盖距离的下标则说明当前最远覆盖距离的下标已经到达终点,不需要再走一步了。
lass Solution {
    public int jump(int[] nums) {
    	int ans =0;//记录走的步数
    	int cur =0;//当前最远覆盖距离的下标
    	int next =0;//下一步最远覆盖距离的下标
    	for(int i=0;i<nums.length-1;i++) {//注意这里是小于nums()-1
    		next = Math.max(next, i+nums[i]);//更新下一次最远覆盖距离下标
    		if(i==cur) {//遇到当前最远覆盖距离的下标
    			cur = next;//更新当前最远覆盖距离下标
    			ans++;
    		}
    	}
    	return ans;
    }
}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值