LeetCode 198:打家劫舍

链接
题目
在这里插入图片描述

思路一:动态规划

在这里插入图片描述

  • dp定义:在 i 位置能抢到最多的钱是多少;

  • 状态和选择
    状态只有索引 i ,选择即 选择 还是 不偷,哪个钱多就选哪个;

  • base case
    dp[0]=nums[0] 即在第一个房子时,能偷到的最多的钱就是直接偷 !不用犹豫 !

由于for循环中有 i-2,所以单独拎出 i=1时的情况;

class Solution {
    public int rob(int[] nums) {
        if(nums==null || nums.length==0){
            return 0;
        }
        if(nums.length==1){
            return nums[0];
        }
        //dp定义:第i间屋子时可以偷的最多的钱
        int n=nums.length;
        int[] dp=new int[n];
        //base case
        // 到第0索引处能偷的最大即为nums[0]
        dp[0]=nums[0];
        dp[1]=Math.max(0+nums[1] , dp[0]);
        for(int i=2;i<n;i++){
            // 要么偷,即i-1不能被偷,钱是i-2和nums[i]; 不偷,则i-1被偷!
            dp[i]=Math.max(dp[i-2]+nums[i] , dp[i-1]);
        }
        return dp[n-1];
    }
}

思路二:动态规划+递归

  • dp定义:以start为起点,可以偷的最多的钱是多少, 所求即 dp(nums,0) ;

  • 状态和选择
    状态:就是起点start,即小偷所处的位置即nums数组的索引;
    选择:当前要么抢,要么不抢,如果不抢则start想前走+1,如果抢,则要加上当前nums中start位置的钱,然后start+2 !

  • base case:
    如果 start > nums.lenth-1 ,则为0 ,即起点超过最后一家就抢不到了;

  • 重叠子问题

class Solution {
    int memo[];
    public int rob(int[] nums) {
        memo=new int[nums.length];
        Arrays.fill(memo,-1); // 初始化dp
        return dp(nums,0);
        // memo定义:从 i出发能抢到最多的钱总数
    }

    int dp(int[] nums,int start){ // start就对应题目数组的索引;
        // base case ,即start超过最后一间房子后,抢到的为0
        if(start>=nums.length){
            return 0;
        }

        // 重叠子问题
        if(memo[start]!=-1){
            return memo[start];
        }
        // 状态转移(选择):不抢 or 抢
        memo[start]=Math.max( dp(nums,start+1) , dp(nums,start+2)+nums[start] );
        return memo[start];
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值