0
点赞
收藏
分享

微信扫一扫

打家劫舍(动归模板讲解的妙啊)(注意dp[k] 是前k间房子的最大值,最后一间房子是nums[k-1], 不是nums[k]) (用 prev 和 curr 来代替dp[k-2] 和 dp[k-1)

乌龙茶3297 2022-02-26 阅读 19

(动归模板讲解的妙啊)(注意dp[k] 是前k间房子的最大值,最后一间房子是nums[k-1], 不是nums[k]) (用 prev 和 curr 来代替dp[k-2] 和 dp[k-1], 用 tem 来代替 dp[k]

文章目录

动归模板讲解绝了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目

在这里插入图片描述
在这里插入图片描述

代码

dp[k] 代表从前k间房子能获得的最多的钱,不能偷相邻房子的钱,从0 —> k ,这样,在算后面的dp[k]的时候。前面的dp值早都求出来了

for循环里 i <= nums.length; 而不是i <=nums.length-1; 因为要求前nums.length间房子能取得的钱,注意把握dp数组的含义。(而且也不会访问nums[i],所以不会越界,本题唯一绕人的地方就在这)

class Solution {
    public int rob(int[] nums) {
        if(nums.length == 1){
            return nums[0];
        }

        int[] dp = new int[nums.length+1];    // dp[k] 代表从前k间房子能获得的最多的钱,不能偷相邻房子的钱,从0 —> k ,这样,在算后面的dp[k]的时候。前面的dp值早都求出来了

        // 初始化
        dp[0] = 0;
        dp[1] = nums[0];
        for(int i = 2; i <= nums.length; i++){  // 这里 i <= nums.length; 而不是i <=nums.length-1; 因为要求前nums.length间房子能取得的钱,注意把握dp数组的含义。(而且也不会访问nums[i],所以不会越界,本题唯一绕人的地方就在这)
            dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i-1]); // 注意:当前处理的前 i 个房子 的最后一个房子是nums[i-1], 不是 nums[i]
        }

        return dp[nums.length]; // 返回值 是 dp[nums.length],代表从前nums.length - 1个房子所能获得的最多的钱,而不是dp[nums.length-1];


    }
}

空间优化后的代码

class Solution {
    public int rob(int[] nums) {
        int prev = 0;   // 一开始代表 0
        int curr = 0;   // 一开始代表 0

        // 每次循环,计算“偷到当前房子为止的最大金额”
        for (int i : nums) {    // 从第 0 个开始 ,一次循环过后 prev就得值就变成了dp[0], curr就变成了 dp[1]
            // 循环开始时,curr 表示 dp[k-1],prev 表示 dp[k-2]
            // dp[k] = max{ dp[k-1], dp[k-2] + i }
            int temp = Math.max(curr, prev + i);
            prev = curr;
            curr = temp;
            // 循环结束时,curr 表示 dp[k],prev 表示 dp[k-1]
        }

        return curr;
    }

}
// @solution-sync:end

举报

相关推荐

0 条评论