“打家劫舍”系列总结,偷不偷这个房间呢?(Java实现)

news2024/9/28 13:22:16

目录

前言

一、打家劫舍 ——>房子是线性的

1.1、dp定义

1.2、递推公式

1.3、初始化

1.4、遍历顺序

1.5、解题代码

二、打家劫舍II ——>房子是环型

2.1、分析

2.2、解题代码

三、打家劫舍III ——>房子是树形

3.1、dp含义

3.2、递推公式

3.3、解题代码

小结


前言

        本篇题目虽然可以使用其他方法,如暴力枚举、贪心来解,但是只是针对特定场景的问题才可以,所以这里我将用动态规划的方法来教你,怎么偷,才能偷到最多钱~


一、打家劫舍 ——>房子是线性的

题目描述:

题目来源:198. 打家劫舍

1.1、dp定义

分析:

        我们需要考虑到每一个房间,并且得出可以偷盗的最大金额,因此dp数组的数值就是我们能偷到的最大金额,就对应第几天~

dp定义:

dp[i]:考虑偷第i个房间(包括之前的房间),可以偷盗的最大金额。

1.2、递推公式

分析:

dp[i]有几种状态?从哪些状态可以推出dp[i]?

        一个房间无非就是两种状态,偷或者不偷,根据题目描述,不能连续偷盗两个相邻的房间,所以,当前这个房间如果我们不去偷他,那么当前所拥有的最大金额就是前一个状态dp[i - 1]这个时候所拥有的最大金额,如果要偷,那么前一天一定不能偷,那么当前所拥有的最大金额就是dp[i - 2] + nums[i],也就是不考虑昨天,加上今天一定偷所能获得的最大金额

递推公式:

dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);

1.3、初始化

分析:

        从递推公式中可以看出需要用到两个状态,dp[i - 1]和dp[i - 2],将这两个状态一直推下去,就可以知道我们需要初始化的是dp[0]和dp[1];

dp[0]表示考虑偷第1个房间,那么现在总共就一个房间,肯定是要偷的。

dp[1]表示考虑偷第2个房间(包括之前的房间),那么现在总共就两个房间,由于不能连续偷相邻房间,因此就偷这两个房间价值最大的。

初始化:

dp[0] = nums[0];

dp[1] = Math.max(nums[0], nums[1]);

1.4、遍历顺序

由递推公式可以知道,要推出当前dp[i],需要知道前两天的状态,所有从左往右遍历即可。

1.5、解题代码

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

二、打家劫舍II ——>房子是环型

题目描述:

题目来源: 213. 打家劫舍 II

2.1、分析

 思考:

        虽然房子是一个环型,无非就是要多考虑一个问题,因为不能连续偷盗两个相邻的房间,所以第一个房间和最后一个房间只能偷一个,那么我们可以把它想象成两个线性的结构,如下图:

 

本题与“打家劫舍”这道题一样,最后问的都是所能偷盗的最大价值,因此就可以把题目所给的房间截取成上图中的两端,然后分别用“打家劫舍”那道题的方式进行处理,最后比较出 “偷第一个不偷最后一个” 和 “不偷第一个偷最后一个” 的最大值,就是我们要求的最大价值。

2.2、解题代码

class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        if(len == 1) return nums[0];
        if(len == 2) return Math.max(nums[0], nums[1]);
        int first = robI(Arrays.copyOfRange(nums, 0, len - 1));
        int last = robI(Arrays.copyOfRange(nums, 1, len));
        return Math.max(first, last);
    }

    private int robI(int[] nums) {
        int len = nums.length;
        if(len == 1) return nums[0];
        if(len == 2) return Math.max(nums[0], nums[1]);
        int[] dp = new int[len];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for(int i = 2; i < len; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }
        return dp[len - 1];
    }
}

三、打家劫舍III ——>房子是树形

题目描述:

 

题目来源:337. 打家劫舍 III 

3.1、dp含义

分析:

        房子是一个树形,我们可以采取一个后续遍历的方式(后面会讲原因),去遍历这颗树,最后得出最大值;

房子只有两种状态,偷或者不偷,我们可以用Pair键值对的形式来保存这两种状态,我们只需要在后序遍历的过程中写下Pair,那么每一个结点都有一个Pair这两种状态,因此可以延续。

初始化:

Pair<Integer, Integer> dp :表示当前房屋偷(getValue())和不偷(getKey())两种最大价值。

最后返回两者最大值即可。

3.2、递推公式

分析:

房子只有偷和不偷两种状态,那么

1.如果偷当前房子,就一定不可以偷当前结点的两个子节点,因此偷当钱房屋的最大价值就是,不偷两个子节点的最大价值(使用后续遍历的原因:这里的子节点的值从何而来,就是需要后序遍历先得到值,现在才能用子节点的返回值) + 当前结点的价值 ——> dpLeft.getKey() + dpRight.getKey() + root.val;

2.如果不偷当前房子,那么两个子节点可以偷也可以选择不偷(比如就拿其中一个子节点来说,这一个子节点可以偷也可以不偷,需要从这两种状态种选出一个最大值),分别得出一个最大值即可,然后求和就是当前所拥有的最大价值 ——>Math.max(dpLeft.getKey(), dpLeft.getValue()) + Math.max(dpRight.getValue(), dpRight.getKey());

动态转移方程:

int val1 = Math.max(dpLeft.getKey(), dpLeft.getValue()) +
        Math.max(dpRight.getValue(), dpRight.getKey());//不偷当前结点
int val2 = dpLeft.getKey() + dpRight.getKey() + root.val;//偷当前结点

3.3、解题代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    public int rob(TreeNode root) {
        Pair<Integer, Integer> dp = dfs(root);
        return Math.max(dp.getKey(), dp.getValue());
    }

    private Pair<Integer, Integer> dfs(TreeNode root) {
        if(root == null) {
            return new Pair<>(0, 0);
        }
        Pair<Integer, Integer> dpLeft = dfs(root.left);
        Pair<Integer, Integer> dpRight = dfs(root.right);
        int val1 = Math.max(dpLeft.getKey(), dpLeft.getValue()) +
        Math.max(dpRight.getValue(), dpRight.getKey());//不偷
        int val2 = dpLeft.getKey() + dpRight.getKey() + root.val;
        return new Pair<>(val1, val2);
    }

}

小结

小偷这么聪明,为啥还要来偷?


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/186640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Trusted Firmware-A 移植】

Trusted Firmware-A 移植Trusted Firmware-A 简介步骤一、解压标准 tf-a 源码包,进入 tf-a 源码目录下&#xff1a;二、将 ST 官方补丁文件打到 tf-a 源码中&#xff1a;三、配置交叉编译工具链四、添加设备树文件五、编译源码六、固件烧写结果Trusted Firmware-A 简介 嵌入式…

Magisk工具使用指南

对于一般玩机用户,Magisk官方提供的发布版本即可满足要求,但对于高级开发者来说这远远不够,我们不仅仅是满足于使用,更要学会定制面具,最好的能完全理解面具的核心架构以便于自己也能写出来一套和面具差不多的工具,这才是我们研究面具最根本的原因所在。因为做移动安全,…

edp 基本信号-参数及命令

基本信号及概念通信双方及通道下图为edp规范中的总体框图。通过此框图我们可以了解到&#xff1a;交互的双方&#xff1a;1&#xff09;source device 即 显卡的显示控制部分2) sink device 即 显示屏 双方间的通道&#xff1a;1&#xff09; HPD 即热插拔&#xff0c;通过sink…

mysql之6中索引失效情况

对索引使用左或者左右模糊匹配 mysql> explain select * from user where name王五; -------------------------------------------------------------------------------------------- | id | select_type | table | type | possible_keys | key | key_len | ref …

2023.1.30---TF-A相关

完成TF-A源码的移植过程在tf-a源码目录下将补丁文件打到tf-a源码中2.在上级目录中的Makefile.sdk文件中&#xff0c;配置交叉编译工具链&#xff0c;找到CROSS_COMPILE将红色部分改为arm-linux-gnueabihf-3.在fds目录下添加设备树文件4.在上级目录中的Makefile.sdk文件中&#…

全世界游客访问最多的城市,重庆以5.9亿游客量排名第一

经过全面开放和“阳康”&#xff0c;旅游市场已经开始复苏。现在恰逢寒冬&#xff0c;海南等国内许多旅游胜地成为热门旅游目的地&#xff0c;泰国等国际旅游频频上热搜。旅游市场目前现状如何跟随《旅游市场数据报告》一起来了解吧。全国5A景区数量全国共有318个景区被评为AAA…

重温数据结构与算法之约瑟夫问题

文章目录前言一、暴力法二、动态规划三、实战3.1 力扣 1823. 找出游戏的获胜者3.2 洛谷 P1996 约瑟夫问题参考前言 约瑟夫问题&#xff0c;是一个计算机科学和数学中的问题&#xff0c;在计算机编程的算法中&#xff0c;类似问题又称为约瑟夫环&#xff0c;又称“丢手绢问题”…

K8s关键性概念图解

Kubernetes可以看做云原生时代的操作系统&#xff0c;统一管理下层的基础设施&#xff0c;如计算资源、网络资源、存储资源等等。将集群中存在的各种复杂关系抽象成各种API资源&#xff0c;以统一的方式暴露出各种接口&#xff0c;也便于未来的扩展以及开发团队根据自己的需要定…

JS创建ZIP文件,JSZip的使用

Hi I’m Shendi 最近编写压缩工具&#xff0c;需要使用js创建zip文件&#xff0c;使用 JSZip 插件 官网&#xff1a; https://stuk.github.io/jszip/ Github&#xff1a; https://github.com/Stuk/jszip https://sdpro.top/blog/html/article/1012.html 下载 NPM : npm inst…

论文笔记:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis

目录 文章摘要 1 Neural Radiance Field Scene Representation (基于神经辐射场的场景表示) 2 Volume Rendering with Radiance Fields (基于辐射场的体素渲染) 2.1 经典渲染方程 2.2 经典的体素渲染方法 2.3 基于分段采样近似的体素渲染方法 3 Optimizing a Neural Rad…

高通开发系列 - linux kernel启动阶段串口无打印采用LED点灯

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 问题背景kernel启动汇编探测kernel启动C函数阶段探测这篇文章之前请参考下:高通开发系列 - MSM8909指示灯操作 问题背景 最近在基于…

38. 外观数列

打卡!!!每日一题 今天给大家带来一道比较有意思的题目&#xff0c;先看看题目描述 题目描述&#xff1a; 题目示例&#xff1a; 大家题目读完可能还没太理解什么意思&#xff0c;我简单给大家翻译翻译&#xff1a; n&#xff1a;表示我们要计算多少次 每一次都是对前面一个…

详细介绍Sentence-BERT:使用连体BERT网络的句子嵌入

Sentence-BERT:Sentence Embeddings using Siamese BERT-Networks 使用连体BERT网络的句子嵌入 BERT和RoBERTa在诸如语义文本相似性&#xff08;STS&#xff09;的句子对回归任务上创造了新的最优的性能。然而&#xff0c;它要求将两个句子都输入网络&#xff0c;这导致了巨大的…

代码随想录--二叉树章节总结Part IV 完结篇

代码随想录–二叉树章节总结Part IV 完结篇&#x1f389; 1.Leetcode501 二叉树中的众数 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如…

大数据行业如何获取高薪岗位offer?

在互联网行业需要保持不断的学习。学习大数据先思考自身未来想往哪个方向发展&#xff0c;想要入门快、基础深厚&#xff0c;并且需求多应用广建议从JAVA开始学起&#xff0c;找到适合自己的学习方法。 大数据行业人才稀缺&#xff0c;据第三方统计2020年全国招收程序员394699…

mybatis-plus2

目录 一、乐观锁 二、乐观锁与悲观锁的区别 1.乐观锁和悲观锁的应用场景 三、条件查询构造器 四、分页查询 五、逻辑删除 六、在Mybatis-plus中使用xml配置 一、乐观锁 乐观锁插件 | MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/pages/0d93c0/ 当要更新一条…

16. JSON解析

1. 什么是 JSON &#xff1f; JSON 指的是 JavaScript 对象表示法&#xff08;JavaScript Object Notation&#xff09;。 JSON 是轻量级的文本数据交换格式。 JSON 独立于语言&#xff1a;JSON 使用 Javascript语法来描述数据对象&#xff0c;但是 JSON 仍然独立于语言和平台…

Kettle基础操作

目录 Kettle基础操作 1 启动Kettle 2 创建本地资源库 3 基础操作 3.1 新建转换 3.2 新建作业 3.3 节点连接 4 导入/导出资源库 5 创建数据库连链接 Kettle基础操作 1 启动Kettle 前置环境&#xff1a;JDK 1.7以上、IE浏览器升级至IE10以上&#xff08;Kettle7.0以下…

Java——打家劫舍

题目链接 leetcode在线oj题——打家劫舍 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff…

Hive数仓建设手册

1 数仓的分层及建模理论 1.1 数据仓库的用途 整合公司所有业务数据&#xff0c;建立统一的数据中心产生业务报表&#xff0c;用于作出决策为网站运营提供运营上的数据支持可以作为各个业务的数据源&#xff0c;形成业务数据互相反馈的良性循环分析用户行为数据&#xff0c;通…