代码随想录第四十天|打家劫舍 |打家劫舍II |打家劫舍III

打家劫舍

这个就和爬楼梯很像,只不过这个每次只能走两步,求最后偷到钱的最大价值。

动规五部曲:

  1. dp[i]代表到下标i的家里时,考虑偷还是不偷的最大价值,这里的考虑非常重要,如果偷下标i的房间,那么dp[i]=dp[i-2]+nums[i]。如果不偷,那就是dp[i]=dp[i-1];因为偷了当前房间,i-1房间就不能偷了。
  2. 所以递推公式:dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
  3. 初始化,dp[0]=nums[0],dp[1]=max(nums[0],nums[1])
  4. 遍历顺序,从前往后
java 复制代码
class Solution {
    public int rob(int[] nums) {
        if(nums.length==1){
            return nums[0];
        }
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        dp[1]=Math.max(nums[0],nums[1]);
        for(int i=2;i<nums.length;i++){
            dp[i]=Math.max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[nums.length-1];
    }
}

打家劫舍 II

这里数组变成了环形的,首位相连。头节点和尾结点不能同时取。那就进行分类,分成只取头结点时所能偷的最大钱数和只取尾结点时所能偷的最大钱数。

  1. dp[i]表示到下标为i的房间时,考虑偷还是不偷所能得到的最大钱数为dp[i]
  2. 递推公式:dp[i]=max(dp[i-2]+nums[i],dp[i-1]),两种情况的递推公式都是一样的,只是在初始化的时候和遍历的时候有区别
  3. 初始化:只考虑头结点:dp1[0]=nums[0],dp1[1]=max(nums[0],nums[1]);只考虑尾结点:dp2[1]=nums[1],dp2[2]=max(nums[1],nums[2]);
  4. 遍历顺序:只考虑头结点时,从下标0开始遍历到nums.length-2,只考虑尾结点时,从下标1开始遍历到nums.length-1
java 复制代码
class Solution {
    public int rob(int[] nums) {
        if(nums.length==1){
            return nums[0];
        }
        if(nums.length==2){
            return Math.max(nums[0],nums[1]);
        }
        int[] dp1=new int[nums.length-1];//考虑首元素
        int[] dp2=new int[nums.length];//考虑尾元素
        dp1[0]=nums[0];
        dp2[0]=0;
        dp1[1]=Math.max(nums[0],nums[1]);
        dp2[1]=nums[1];
        dp2[2]=Math.max(nums[1],nums[2]);
        for(int i=2;i<nums.length-1;i++){
            dp1[i]=Math.max(dp1[i-2]+nums[i],dp1[i-1]);
        }
        for(int i=3;i<nums.length;i++){
            dp2[i]=Math.max(dp2[i-2]+nums[i],dp2[i-1]);
        }
        return Math.max(dp1[nums.length-2],dp2[nums.length-1]);
    }
}

打家劫舍 III

这是将数组改成了二叉树,这是树形dp的入门题。既然是二叉树,就要考虑使用什么遍历方式,递归和递归三部曲。这里必须使用后序遍历,因为要先将两个孩子上的最大钱数算出来,然后去当前节点偷还是不偷进行比较,如果不偷当前节点,那就偷孩子节点。

动规五部曲:

  1. dp[i]代表到节点i时,偷当前节点的最大钱数为dp[1],不偷当前节点的最大钱数为dp[0]
  2. 递推公式:偷当前节点:val1=cur.val+leftdp[0]+rightdp[0];不偷当前节点:val2=max(leftdp[1],leftdp[0])+max(rightdp[1],rightdp[0]);最终返回值为{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}
  3. 初始化:递归不用初始化
  4. 遍历顺序:按照递归

递归三部曲:

  1. 确定参数和返回值:参数就为根节点,返回值为根节点的{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}
  2. 终止条件:当遍历到叶子节点后,直接返回{0,0};
  3. 单层处理逻辑:就是偷当前节点和不偷当前节点的最大钱数
java 复制代码
class Solution {
    public int rob(TreeNode root) {
        int[] dp=robby(root);
        return Math.max(dp[0],dp[1]);
    }
    public int[] robby(TreeNode cur){
        if(cur==null){
            return new int[]{0,0};
        }
        int[] leftdp=robby(cur.left);
        int[] rightdp=robby(cur.right);
        //偷当前节点=当前节点价值+不偷左右子节点
        int val1=cur.val+leftdp[0]+rightdp[0];
        //不偷当前节点=左右子节点偷与不偷的最大价值
        int val2=Math.max(leftdp[0],leftdp[1])+Math.max(rightdp[0],rightdp[1]);
        return new int[]{val2,val1};
    }
}
相关推荐
艾莉丝努力练剑18 分钟前
【优选算法必刷100题】第031~32题(前缀和算法):连续数组、矩阵区域和
大数据·人工智能·线性代数·算法·矩阵·二维前缀和
醉颜凉19 分钟前
环形房屋如何 “安全劫舍”?动态规划解题逻辑与技巧
c语言·算法·动态规划
大雨淅淅22 分钟前
一文搞懂动态规划:从入门到精通
算法·动态规划
不去幼儿园25 分钟前
【启发式算法】灰狼优化算法(Grey Wolf Optimizer, GWO)详细介绍(Python)
人工智能·python·算法·机器学习·启发式算法
随意起个昵称26 分钟前
【二分】洛谷P2920,P2985做题小记
c++·算法
没书读了32 分钟前
计算机组成原理-考前记忆清单
线性代数·算法
Hcoco_me1 小时前
大模型面试题5:矩阵(M*M)特征值分解的步骤
算法·机器学习·矩阵
非著名架构师2 小时前
极端天气下的供应链韧性:制造企业如何构建气象风险防御体系
大数据·人工智能·算法·制造·疾风气象大模型·风光功率预测
星轨初途2 小时前
数据结构排序算法详解(2)——选择排序(附动图)
c语言·数据结构·经验分享·笔记·b树·算法·排序算法
kaikaile19953 小时前
基于 MATLAB 的室内三维定位
算法