代码随想录刷LeetCode | 动态规划打家劫舍刷题回顾

目录

题目回顾

动态规划相关章节

动态规划五步法:

​编辑

1.打家劫舍 

思路:二刷时将状态分成了偷第i家和不偷第i家的情况

2.打家劫舍II  

思路:成环的三种情况:偷首不偷未、偷未不偷首、首位都不偷

3.打家劫舍III

总结


前沿:撰写博客的目的是为了再刷时回顾进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。

预:看到题目后的思路和实现的代码。

见:参考答案展示。

感思:对比答案后的思考,与之前做过的题目是否有关联。

行:

(1)对于没做出来的题目,阅读答案后重新做一遍;

(2)下次做题可以尝试改善的方向;

(3)有助于理解的相关的题目

优先级:做题进度>学习&总结>默写回顾>做题数量

题目回顾

动态规划相关章节

代码随想录刷LeetCode | day39 动态规划刷题回顾

代码随想录刷LeetCode | day41 动态规划刷题回顾

动态规划五步法:

  1. 确定dp数组以及下标的含义
  2. 确定递推公式

  3. dp数组如何初始化

  4. 确定遍历顺序

  5. 举例推导dp数组

1.打家劫舍 

题目链接:198.打家劫舍 

思路:二刷时将状态分成了偷第i家和不偷第i家的情况

相邻报警 -> 偷窃到的最高金额
dp[i] 表示遍历到第i间房子时能够偷到的最大金额
        [0] 表示偷第i间房子的能够偷到的最大金额
        [1] 表示不偷第i间房子的能够偷到的最大金额
递推公式:
        dp[i][0] = dp[i-1][1]+nums[i];
        dp[i][1] = Math.max(dp[i-1][0],dp[i-1][1]);

class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        int[][] dp = new int[len][2];
        dp[0][0] = nums[0];
        dp[0][1] = 0;
        for(int i = 1;i < len;i++){
            dp[i][0] = dp[i-1][1]+nums[i];
            dp[i][1] = Math.max(dp[i-1][0],dp[i-1][1]);
        }
        return Math.max(dp[len-1][0],dp[len-1][1]);
    }
}

2.打家劫舍II  

题目链接:213.打家劫舍II 

思路:成环的三种情况:偷首不偷未、偷未不偷首、首位都不偷

dp[i] 偷到i家时,最高能偷金额

dp[i] = dp[i-1],dp[i-2]+nums[i]

class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        if(len == 0){
            return 0;
        }
        else if(len == 1){
            return nums[0];
        }
        else if(len == 2){
            return Math.max(nums[0],nums[1]);
        }
        //左闭右开
        return Math.max(getRob(nums,0,len-1),getRob(nums,1,len));
    }
    int getRob(int[] nums,int begin,int end){
        int[] dp = new int[end];
        dp[begin] = nums[begin];
        dp[begin+1] = Math.max(nums[begin],nums[begin+1]);
        for(int i = begin+2;i < end;i++){
            dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
        }
        return dp[end-1];
    }

}

3.打家劫舍III

题目链接:337.打家劫舍III

class Solution {
    public int rob(TreeNode root) {
        // 树-深度优先遍历or广度优先遍历?
        // 只有通过深度的后序遍历才能从后往前推,直至根节点。
        // 递归三步曲+动态规划五步法
        // 3.遍历顺序:后序遍历
        int[] dp = dp(root);
        return Math.max(dp[0],dp[1]);

    }
    public int[] dp(TreeNode node){
        // 1.递归的参数和返回值:返回节点 and 当前节点的dp值
        // int[] dp = new int[2];0表示偷的最大值,1表示不偷当前的最大值
        // 2.递归终止条件(dp初始化):叶子节点返回dp[0] = dp[1] = 0;
        int[] res = new int[2];
        if(node == null){
            return res;
        }
        // 4.递归单层逻辑
        int[] left = dp(node.left);
        int[] right = dp(node.right);

        res[0] = Math.max(left[0],left[1])+Math.max(right[0],right[1]);
        res[1] = left[0]+right[0]+node.val;
        return res;

    }

}

总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值