LeetCode(198. 打家劫舍)

如题在这里插入图片描述
审题,偷了第i家以后是两种可能的做法,偷i+2家或者偷i+3家的,首先用回溯穷举试试

public static void doalone(int idex,int[] nums,int sum,int[]re){
        if(idex<nums.length){
            sum+=nums[idex];
            doalone(idex+2,nums,sum,re);//偷隔一位
            doalone(idex+3,nums,sum,re);//偷隔两位
            sum-=nums[idex];
        }else{
            if(sum>re[0]){//与原有最大值比较
                re[0]=sum;
            }
        }
    }

很显然当这街道太长会超限
在这里插入图片描述
另一种自然是动态规划实现了
对于有i家时的最大值,对于第i家有两种可能,由此推导

if(nums.length==0){
            return 0;
        }
        if(nums.length==1){
            return nums[0];
        }
        int[] []dp = new int[nums.length][2];
        dp[0] [0]=0;//第一户不偷
        dp[0][1]=nums[0];//第一户偷
        dp[1][1]=nums[1];//偷第二户
        dp[1][0]=nums[0];//不偷第二户
        for(int i=2;i<nums.length;i++){
            dp[i][0]=dp[i-1][1]>dp[i-2][1]?dp[i-1][1]:dp[i-2][1];//不偷该户最大为偷前一户最大和前两户最大中的较大值
            dp[i][1]=dp[i-1][0]>dp[i-2][1]?dp[i-1][0]+nums[i]:dp[i-2][1]+nums[i];//偷该一户的最大为不偷前一户最大与偷前两户最大中的较大值家当钱户
        }
        return dp[nums.length-1][0]>dp[nums.length-1][1]?dp[nums.length-1][0]:dp[nums.length-1][1];//偷和不偷的较大值
    }

在这里插入图片描述
换一种思路,是否可以直接缓存必偷第i家时的最大值呢,那也是可以的

public  static int rob2(int[] nums) {
        if(nums.length==0){
            return 0;
        }
        if(nums.length==1){
            return nums[0];
        }
        int [] dp =new int[nums.length+2];//缓存偷该家的最大值
        dp[0]=nums[0];
        dp[1]=nums.length>1?nums[1]:0;
        dp[2]=nums.length>2?nums[2]+nums[0]:0;
        for(int i=3;i<nums.length;i++){
            dp[i]=dp[i-2]>dp[i-3]?dp[i-2]+nums[i]:dp[i-3]+nums[i];//偷第i家的最大值为偷第i-2家与偷第i-3家中的较大值加上该家
        }
        return dp[nums.length-1]>dp[nums.length-2]?dp[nums.length-1]:dp[nums.length-2];//偷最后一家或者偷倒数第二家的较大值
    }

结果倒是相差不大在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值