动态规划篇-03:打家劫舍

198、打家劫舍

状态转移方程

 base case

边界问题就是:走到最后一间房子门口也没抢,那么最终抢到的金额为0

明确状态

“原问题和子问题中会变化的变量”

抢到的金额数就是状态,因为随着在每一件房子门口做选择,抢到的金额数会随之变化

确定选择

“导致状态变化的行为”

在每间房子门口都可以做出两个选择:“抢”或者“不抢”。如果抢了的话那么下一间就不能抢,如果这件不抢的话下一间就可以抢

定义dp函数

根据题意,定义dp(n) 为:n间房子能抢到的最大金额数

此外,还要考虑从第几间房子开始抢。那么dp函数应该有两个参数:从第几间房子开始-start,可抢的房子数组-nums

那么状态转移方程就是:

dp(nums,start) = Math.max(nums[start] + dp(nums,start + 2),
                    dp(nums,start + 1));
//nums[start] + dp(nums,start + 2    表示从第start家开始抢,抢到的金额自然是第start家的金额
//加上从start+2家开始抢得到的金额
//dp(nums,start + 1) 表示第start家不抢了,从下一家开始抢

 我们可以看到,这里再次体现了

“[分解问题]的思路可以扩展成动态规划算法。”

我们把“从第start间房子开始抢到的金额”这个问题分解为:“从下下间房子开始抢” 和 “从下一间房子开始抢”  两个子问题

有了状态转移方程,我们就可以写出最基础的暴力递归解法了

暴力递归

class Solution {
    public int rob(int[] nums) {
        return dp(nums,0);
    }
    /*dp函数表示从第 start 间房子开始抢的最大金额*/
    int dp(int[] nums,int start){
        /*如果这排房子从头到尾都挑完了还没开始抢,那就什么也抢不到*/
        //base case
        if(start >= nums.length){
            return 0;
        }
        
        /*在每个房子门前有两种选择,抢 / 不抢*/
        int res = Math.max(nums[start] + dp(nums,start+2)
                , dp(nums,start+1));
        return res;
    }
}

这种解法显然时间复杂度太高。按照我们之前所讲的:通过处理“重叠子问题”来降低时间复杂度

使用了备忘录的从上到下的递归解法

class Solution {
    public int rob(int[] nums) {
        int[] memo = new int[nums.length];
        //初始化备忘录数组
        Arrays.fill(memo,-1);
        return dp(nums,0,memo);
    }
    int dp(int[] nums,int start,int[] memo){
        //base case
        if(start >= nums.length){
            return 0;
        }
        //如果备忘录中存有这个数值,就直接取用
        if(memo[start] != -1){
            return memo[start];
        }
        //状态转移方程
        memo[start] = Math.max(dp(nums,start+1,memo),
                nums[start] + dp(nums,start+2,memo));
        return memo[start];
    }
}

问题1:如何判断该问题是否能够优化?

根据前面的文章我们已将知道:我们可以通过优化“重叠子问题”来降低时间复杂度。那么我们怎么才能知道是否存在“重叠子问题”呢?

抽象出递归框架,先找出 [状态] ,然后根据递归框架看看:如果从一个状态转移到另一个状态有不止一条路径,那么说明存在 [重叠子问题]

使用了dp数组的从下到上的迭代解法

class Solution {
    /*从下到上的迭代数组解法*/
    public int rob(int[] nums) {
        int n = nums.length;
        //为什么数组长度定义为 n+2?
        /*dp[i] 表示从第 i 家开始抢劫获得的金额数,0~n*/
        int dp[] = new int[n + 2];

        for (int i = n-1; i >= 0; i--) {
            dp[i] = Math.max(nums[i] + dp[i+2],
                    dp[i+1]);
        }
        return dp[0];
    }
}

问题1:为什么dp数组长度定义为 n + 2呢?

因为dp[i] 与dp[i+2] 和dp[i+1]有关,为了防止数组越界,将数组长度定为n+2


如果有什么不明白或者文章中内容有误,请在评论区留言。我看到后会一一回复。

及时收获反馈,这对我很重要。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity中的异步编程【7】——在一个异步方法里播放了animation动画,取消任务时,如何停止动画播放

用一个异步方法来播放一个动画,正常情况是:动画播放结束时,异步方法宣告结束。那如果我提前取消这个异步任务,那在这个异步方法里面,我要怎么停止播放呢?! 一、播放animation动画的异步实现 1…

RIP【新华三与华为区别】

【介绍】 rip分为rip 1 与 rip 2 ,rip 2 是对 rip 1 的一种升级,rip 2 可以进行认证等功能 【命令】 新华三: [HC3-R1] rip #启用rip [HC3-R1-rip] version 2 #告知rip 版本号 [HC3-R1-rip] network 192.168.1.0 #宣告其网段 [HC3-R1-rip] …

【AIGC】电影风格的一组绝美高清图提示词解析

实际示例 女人主角,以时尚电影风格为灵感,追求照片般的逼真度,运用伦勃朗式光线,创造奇幻且细节丰富的场景,充满象征意义,使用3D渲染技术达到8K超高清晰度。 分类相关信息主角女人风格时尚电影风格逼真度…

银行储蓄系统的顶层数据流图及细化数据流图

绘制出银行储蓄系统的顶层数据流图及细化数据流图; 银行储蓄系统存、取款流程如下: 1)业务员事先录入利率信息; 2)如果是存款,储户填写存款单,业务员将存款单键入系统,系统更新储户存…

力扣周赛第二题,下午更新后两道

本题中其实看着条件很多,但是仔细读一下会发现,前四个条件都是固定条件。然后我们再看题。 我们的暴力做法是遍历a数组的字符串a的下标起始下标,然后遍历b数组的字符串b的下标起始下标,进行判断,但是这样会超时&#x…

[软件工具]通用OCR识别文字识别中文识别服务程序可局域网访问

【软件界面】 【算法介绍】 采用业界最先进算法之一paddlocr,PaddleOCR,全称PaddlePaddle OCR,是一种基于深度学习的光学字符识别(OCR)技术。相较于传统的OCR技术,PaddleOCR具有许多优点。 首先&#xff0…

如何创建一个pytorch的训练数据加载器(train_loader)用于批量加载训练数据

Talk is cheap,show me the code! 哈哈,先上几段常用的代码,以语义分割的DRIVE数据集加载为例: DRIVE数据集的目录结构如下,下载链接DRIVE,如果官网下不了,到Kaggle官网可以下到: 1. 定义DriveDataset类&…

Kibana:使用反向地理编码绘制自定义区域地图

Elastic 地图(Maps)附带预定义区域,可让你通过指标快速可视化区域。 地图还提供了绘制你自己的区域地图的功能。 你可以使用任何您想要的区域数据,只要你的源数据包含相应区域的标识符即可。 但是,当源数据不包含区域…

Spring集成

目录 概述1 声朋一个简单的集成流1.1 使用XML定义集成流1.2 使用Java配置集成流1.3 使用Spring lntegration 的 DSL 配置 2 Spring integration 功能概览2.1 消息通道2.2 过滤器2.3 转换器2.4 路由器2.5 切分器2.6 服务激活器2.7 网关2.8 通道适配器2.9 端点模块 概述 就像我们…

RibbonGroup 添加QLineEdit

RibbonGroup添加QLineEdit: QLineEdit* controlEdit new QLineEdit(); controlEdit->setToolTip(tr("Edit")); controlEdit->setText(tr("Edit")); controlEdit->setMinimumWidth(150); …

vue知识-04

计算属性computed 注意: 1、计算属性是基于它们的依赖进行缓存的 2、计算属性只有在它的相关依赖发生改变时才会重新求值 3、计算属性就像Python中的property,可以把方法/函数伪装成属性 4、computed: { ... } 5、计算属性必须要有…

Windows python下载

1、下载 进入到地址:https://www.python.org/dowmloads 可以直接下载最新的版本 或者点击Windows,查看下方更多的版本 点击文档就下载下来啦 2、安装 双击下载的文件,勾选Add python.exe to PATH添加到环境变量中,选择Coutomi…

【数据结构】树和二叉树堆(基本概念介绍)

🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343🔥 系列专栏:《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm1001.2014.3001.5482 ​​ 目录 前言 树的概念 树的常见名词 树与…

Linux工具-搭建文件服务器

当我们使用linux系统作为开发环境时,经常需要在Linux系统之间、Linux和Windows之间传输文件。 对少量文件进行传输时,可以使用scp工具在两台主机之间实现文件传输: rootubuntu:~$ ssh --help unknown option -- - usage: ssh [-46AaCfGgKkMN…

【面试突击】Java面试底层逻辑(HashMap、ConcurrentHashMap面试实战)

🌈🌈🌈🌈🌈🌈🌈🌈 欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理…

HashMap集合万字源码详解(面试常考)

文章目录 HashMap集合1.散列2.hashMap结构3.继承关系4.成员变量5.构造方法6.成员方法6.1增加方法6.2将链表转换为红黑树的treeifyBin方法6.3扩容方法_resize6.3.1扩容机制6.3.2源码resize方法的解读 6.4 删除方法(remove)6.5查找元素方法(get)6.6遍历HashMap集合几种方式 7.初始…

12.2内核空间基于SPI总线的OLED驱动

在内核空间编写SPI设备驱动的要点 在SPI总线控制器的设备树节点下增加SPI设备的设备树节点,节点中必须包含 reg 属性、 compatible 属性、 spi-max-frequency 属性, reg 属性用于描述片选索引, compatible属性用于设备和驱动的匹配&#xff…

pyinstaller,一个超酷的 Python 库!

更多Python学习内容:ipengtao.com 大家好,今天为大家分享一个超酷的 Python 库 - pyinstaller。 Github地址:https://github.com/pyinstaller/pyinstaller PyInstaller是一个用于将Python应用程序打包成独立可执行文件的工具。这可以将Python…

Leading Dimension是什么

在LAPACK中频繁出现Leading Dimension(中文翻译为“主维度”),那么它是什么呢? 首先了解行主序(Row-Major)和列主序(Column-Major)的概念: Given a matrix A of shape …