【Leetcode】45. Jump Game II

题目地址:

https://leetcode.com/problems/jump-game-ii/

给定一个数组,每个数代表当前位置可以向后跳跃的最大步数,允许跳小于这个数字的步数。问从下标 0 0 0出发最少需要多少步可以跳到数组末尾。

基本思路是BFS。我们可以这样想,先将整个数组看成一个有向图的结构,先由 0 0 0出发, a [ 0 ] a[0] a[0]就代表了 1 1 1步所能到达的范围,将这个范围的所有的点看成 0 0 0位置的邻居节点,接着,遍历数组的从 1 1 1 a [ 0 ] a[0] a[0]之间的数字(也就是 0 0 0的所有邻居),对每个数字都去计算它的”最远邻居“,那么显然从 1 1 1步能到达的范围之后一直到这个最远邻居,就是至少两步所能到达的区域,然后以此类推。跳跃次数需要每次开始遍历”下一层邻居“的时候累加一次,直到某次能跳到结尾,就立刻返回即可。
具体例子如下:对于 ( 2 , 3 , 1 , 1 , 4 ) (2,3,1,1,4) (2,3,1,1,4)首先, 2 2 2 0 0 0次跳跃所能到达的位置,就把第 0 0 0个数字节点看成图的出发节点,或者看成起点节点的”第 0 0 0层邻居“,我们标记一下: ( 2 ( 0 ) , 3 , 1 , 1 , 4 ) (2(0),3,1,1,4) (2(0),3,1,1,4)其次 a [ 0 ] = 2 a[0]=2 a[0]=2,所以至少跳一次所能到达的位置我们也标记一下: ( 2 ( 0 ) , 3 ( 1 ) , 1 ( 1 ) , 1 , 4 ) (2(0),3(1),1(1),1,4) (2(0),3(1),1(1),1,4)标记 1 1 1的节点就是”第 1 1 1层邻居“;接着遍历跳一次能到达的位置,我们就得到了跳两次能到达的位置: ( 2 ( 0 ) , 3 ( 1 ) , 1 ( 1 ) , 1 ( 2 ) , 4 ( 2 ) ) (2(0),3(1),1(1),1(2),4(2)) (2(0),3(1),1(1),1(2),4(2))我们发现在更新跳两次能跳到的位置的时候,数组终点成为了标记 1 1 1的数字中某个数字的邻居,这时候就可以退出了,返回 2 2 2

代码如下:

public class Solution {
    public int jump(int[] nums) {
    	// 判掉不需要跳的情况
    	if (nums.length <= 1) {
            return 0;
        }
        
        int res = 0;
        // 初始化BFS时的队列,其只有一个元素0。[l, r]实际上就是队列里的元素
        int l = 0, r = 0, far = 0;
        // 当队列不空,则BFS
        while (l <= r) {
            res++;
            // 扩展当前层,如果能走到数组末尾则返回步数
            for (int i = l; i <= r; i++) {
                far = Math.max(far, i + nums[i]);
                if (far >= nums.length - 1) {
                    return res;
                }
            }
            
            // 更新队列
            l = r + 1;
            r = far;
        }
        
        return res;
    }
}

时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)

算法正确性是显然的,实际上就是求无权图的最短路长度,由BFS定义即可得到。

注:这题还有个动态规划解法,但复杂度较高,这里就省略了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值