算法学习---跳跃游戏(深度优先&动态规划)

今天闲来没事在力扣上刷算法题,跟一道题就杠上了,把我气得,觉得有必要记录一下。

其实这一道题,一看就是动态规划或递归来做,不过一开始也没仔细去想在这个数据中的递推公式,加上递归写得比较多,自认为比较熟练 ,先用递归来做

深度优先算法(超时)

不一会功夫我就写下了如下代码,麻溜地写出了代码,然后麻溜地超时

class Solution{
    public boolean canJump(int[] nums){
        return gotoEnd(0,nums);
    }

    public boolean gotoEnd(int currentIndex,int[] nums){
        if (currentIndex>=nums.length-1) return true;
        int jump = nums[currentIndex];
        if (jump==0) return false;
        boolean b = false;
        for (int i = jump-1;i>=0;i--){
            int nextIndex = currentIndex+i+1;
            b = b||getoEnd(nextIndex,nums);
            if(b) reutrn b;
        }
        return b;
    }
}

优化深度优先算法(超时)

很容易看出来上面代码是有很多次递归是在做重复的工作的,因为有可能中途从不同的位置跳到相同的下一个位置,就会导致重复的递归,因此用一人上hashmap记录下在当前位置跳到下一个位置的结果,每次递归前先去查一下是否已经执行过此次跳跃,没有执行过再执行方法

class solution{
    Map<Integer,Boolean> map = new HashMap<>();
    public boolean canJump(int[] nums){
        return gotoEnd(0,nums);
    }

    public boolean gotoEnd(int currentIndex,int[] nums){
        if (currentIndex>=nums.length-1) return true;
        int jump = nums[currentIndex];
        if (jump==0) return false;
        boolean b = false;
        for (int i = jump-1;i>=0;i--){
            int nextIndex = currentIndex+i+1;
            if (map.containsKey(nextIndex))
                b = b||map.get(nextIndex);
            else {
                boolean bb = gotoEnd(nextIndex,nums);
                map.put(nextIndex,bb);
                b = b||bb;
            }
            if (b) return b;
        }
        return b;
    }
}

动态规划

上面两个算法都是超时,我也开始思考怎么用动态规划来做,磕磕碰碰做错了很多次,考虑了很多细节,最后写了如下代码,勉强通过题目

class Solution{
	public boolean canJump(int[] nums){
        if (nums.length<2) return true;
        //数组dp[]用来记录dp[i]能到达的最远下标
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
//end记录最远能跳到哪里,end超过数组长度-1(即数组最大下标)即能跳到终点
        int end = nums[0];
        for (int i = 1;i<nums.length-1;i++){
        	//如果到达不了当前位置,就没办法继续往后跳,因而到不了终点
            if (dp[i-1]<i) return false;
            dp[i] = Math.max(dp[i-1],i+nums[i]);
            end = Math.max(dp[i],end);
        }
        return end>=nums.length-1;
    }
}

贴下通过结果和执行时间、内存消耗还有杠上头的提交次数
在这里插入图片描述

优化动态规划

题目通过是通过了,不过这数据也太难看了吧,觉得有必要优化优化,不然写这样的代码以后工作迟早得被老板踢出去, 从上面看未优化的动态坑规划中可以发现

  • dp[i]每次只跟dp[i-1]有关,可以把数组简化成一个变量dp
  • 简化dp[]数组后,dp变量其实就是表示数组能到达的最远下标,其实就是end变量的作用,因此dp变量直接替代了end变量,end变量可以删除
  • 不一定要循环遍历完一遍数组再返回结果,如果中途就发现能到达的最远下标不小于数组最大下标,则能提前返回结果
class Solution {
    public boolean canJump(int[] nums){
        if (nums.length<2) return true;
        int dp = nums[0];
        for (int i = 1;i<nums.length-1;i++){
            if (dp<i) return false;
            dp = Math.max(dp,i+nums[i]);
            if(dp>=nums.length-1) return true;
        }
        return dp>=nums.length-1;
    }
}


最后时间优化了一半,内存消耗还是一点没少,估计也因为是编程语言是Java吧哈哈哈哈

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值