jump games I/II

需求I:

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

分析:

对于元素nums[i],从该点可跳的范围是nums[i+1]~nums[i+nums[i]](确保没有角标越界),假设跳到了nums[i+j],那么我们需要看从点nums[i+j]开始跳是否能到达终点,所以前面的点是否能到达终点依赖于后面的点,所以可以从后向前考虑。

我们可以创建一个长度为nums.length的boolean型数组arr,存储的值表示从该点出发是否能到达终点。如果数组长度是0,那么肯定返回false。设置arr[nums.length-1]=true,表示最后一个点肯定能到终点。从后向前遍历nums数组,对于元素nums[i],设置变量j从1到nums[i]递增,保证不会角标越界,看arr[i+j]是否是true,如果是true,表示从nums[i]可以跳到终点,那么arr[i]=true,break继续判断之前的点。直到遍历到nums[0],而arr[0]就表示是否可以从起点跳到终点。

代码:

class Solution {
    public boolean canJump(int[] nums) {
        //特殊情况判断
        if(nums == null || nums.length == 0)
            return false;
        
        //创建boolean数组,存储的值表示从该点出发是否能到达终点
        boolean[] arr = new boolean[nums.length];
        
        arr[nums.length-1] = true;//最后一个点可以到终点
        
        for(int i = nums.length-2; i >= 0; i--){
            //对于nums[i],可以跳1~nums[i]步
            for(int j = 1; j <= nums[i] && j+i < nums.length; j++){
                if(arr[i+j]){
                    //如果找到了一个为true的下一跳,那么nums[i]就可以到达终点
                    arr[i] = true;
                    break;
                }
            }
        }
        
        return arr[0];//arr[0]表示是否能从起点跳到终点
    }
}

需求II:

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

Example:

Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
    Jump 1 step from index 0 to 1, then 3 steps to the last index.

分析:

思路同I,对于nums[i],其跳跃范围是nums[i+1]~nums[i+nums[i]](保证没有角标越界),假设跳到nums[i+j]并且该点可以到达终点,那么nums[i]到终点的最短跳数,会依赖nums[i+j]到终点的最短跳数,所以还是需要从后向前求解。

创建长度是nums.length的int数组distance,存储每个点到终点的最短跳数,初始化为-1,表示都无法到达终点。设置distance[nums.length-1]=0,表示最后一个节点到终点的最短跳数是0。从后向前遍历,假设遍历到nums[i],其跳跃范围是nums[i+1]~nums[i+nums[i]](保证没有角标越界),如果跳到nums[i+j]处,判断distance[i+j]是否是-1,如果是-1,表示无法到达,继续找其它下一跳,如果不是-1,那么需要判断distance[i]是否是-1,如果是-1,那么更新distance[i]=1+distance[i+j],如果不是-1,更新distance[i] = Math.min(distance[i], distance[i+j]+1)。最终返回distance[0]。但是只通过了91/92,最后一个case直接超时了。

代码:

class Solution {
    public int jump(int[] nums) {
        //异常处理
        if(nums == null || nums.length == 0)
            return 0;
        
        //创建int数组,存储每个点到终点的最短跳数,初始化为-1,0表示终点,-1表示无法达到,正数表示最短跳数
        int[] distance = new int[nums.length];
        Arrays.fill(distance, -1);
        distance[nums.length-1] = 0;
        
        //从后向前遍历,求每个元素到终点的最短跳数
        for(int i = nums.length-2; i >= 0; i--){
            for(int j = 1; j <= nums[i] && j+i < nums.length; j++){
                if(distance[i+j] != -1){
                    if(distance[i] == -1)
                        distance[i] = distance[i+j]+1;
                    else
                        distance[i] = Math.min(distance[i], distance[i+j]+1);
                }
            }
        }
        
        return distance[0];
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值