代码随想录算法训练营第四十八天| LeetCode198.打家劫舍、213.打家劫舍II、337.打家劫舍III

news2024/11/15 13:38:43

一、LeetCode198.打家劫舍(线性)

题目链接/代码讲解/视频讲解:https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html

状态:已解决

1.思路 

        这个题的关键就在于想清楚如何抉择某个房间偷不偷的问题。根据题目,我们知道不能连续进入两间屋子偷窃。也就是说,当前屋子偷不偷取决于前一个房屋与前两个房屋是否被偷(其明面上只与前一个有关,但如果前一个屋子没有偷过,那当前屋子就可以再偷,因此需要对比截止到前两个屋子的偷窃最高金额数+当前屋子的金额 与 偷上一个屋子累积的偷窃最高金额

(1)确定dp数组以及下标含义:

        dp[i]:考虑下标 i (包括i)以内的房屋,最多可以盗窃的金额为i。

(2)确定递推公式:

        dp[i]只有两种来源:

        ① 偷i,则说明 i-1 没被偷,不考虑后面的屋子时,当然是偷了这个屋子的钱总金额最大,故此时dp[i] = dp[i-2]+nums[i];

        ② 不偷i,则说明 i-1 可能偷了也可能没偷,但由于 dp[i-1]代表的是i-1这个屋子所有情况中盗取金额的最大值,故不管i-1偷没偷,我们只需要这个最大值就行,那么此时dp[i]继承dp[i-1],即dp[i] = dp[i-1]。

        取两者中的最大值,即:dp[i] = max(dp[i-2] + nums[i],dp[i-1]);

(3)dp数组初始化:

        由于要看前两个屋子的状态,故需要初始化dp[0]和dp[1],从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1](前两个屋子能够盗窃的最大金额)就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);

        其余下标的值为0,防止值被覆盖。

(4)确定遍历顺序:

        dp[i]是根据前面dp[i-1]和dp[i-2]推出来的,因此一定是从前往后去推。

(5)举例推导dp数组:

        以示例二为例:

dp[nums.size()-1]为结果。 

2.代码实现 

class Solution {
public:
    int rob(vector<int>& nums) {
        vector<int> dp(nums.size(),0);
        if(nums.size()==1) return nums[0];//注意这种特殊情况
        dp[0] = nums[0];
        dp[1] = max(nums[0],nums[1]);
        for(int i=2;i<nums.size();i++){
            dp[i] = max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[nums.size()-1];
    }
};

 时间复杂度: O(n)

空间复杂度: O(n)

二、213.打家劫舍II(环形)

题目链接/代码讲解/视频讲解:https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html

状态:已解决

1.思路 

        这道题跟上面的区别是上面的房间呈直线排列,而这道题的房间是环形排列的。环形意味着首尾相连,因此,我们比线性排列的房间多个限制条件:首尾的房间不能同时盗窃。这个很好实现,我们先去掉尾部的房间按线性房间的方法求一个最大金额,再去掉首部的房间按线性房间的方法求一个最大金额,然后取二者最大值。

        有的同学可能会想,要是最大情况是首尾房间都不偷的话,那我们是不是漏情况了?并没有!我们在求线性房间的最大金额时说了,dp[i]是考虑范围0~i,不代表第i个房间就被偷了,dp[i]包含了第i个房间的所有可能情况。

        这么分析后,基本上跟上道题就大差不差了。

2.代码实现

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size() == 1) return nums[0];
        if(nums.size() == 2) return max(nums[0],nums[1]);
        int result1 = linarRob(nums,0,nums.size()-1);
        int result2 = linarRob(nums,1,nums.size());
        return max(result1,result2);
    }
    int linarRob(vector<int>& nums,int start,int end) {
        vector<int> dp(end-start+1,0);
        if(nums.size()==1) return nums[0];//注意这种特殊情况
        dp[start] = nums[start];
        dp[start+1] = max(nums[start],nums[start+1]);
        for(int i=start+2;i<end;i++){
            dp[i] = max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[end-1];
    }
};

 时间复杂度: O(n)

空间复杂度: O(n)

三、337.打家劫舍III (树形)

题目链接/代码讲解/视频讲解:https://programmercarl.com/0337.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8DIII.html

状态:已解决

1.思路 

        此题也是一个典型的打家劫舍问题,只是对比上两道题又进行了一个升级,变成了树形房间。树形结构中,父节点与左右子节点的偷窃状态有以下几种状态:

(1)偷父节点,那么左右节点一定都不偷,那么父节点的最大金额就是自身金额+左右节点不偷的最大金额的和。

(2)不偷父节点,那么左右节点可偷可不偷,那么父节点的最大金额就是左右节点偷或者不偷的最大金额的和。

        很明显一个节点的最大金额要根据子节点的最大金额决定,因此这题要递归,且是后序遍历的顺序(左右中)。同时,如何取子节点的最大金额也要依赖父节点的偷窃状态,因此需要动规。

        故此题就是一个二叉树和动态规划结合的题,需要在树上进行状态转移,也就是俗称的树形dp

        以递归三部曲为框架,其中融合动规五部曲的内容来进行讲解。

(1)确定递归函数的参数以及返回值(dp数组以及下标含义):

        我们知道需要子节点偷和不偷两种情况的最大金额,因此每层都需要两个容器来保存这两种情况,那我们需要定义2*n大小的数组吗?并不需要!由于递归的特性,我们只需要每层都有一个两个元素的数组即可:即dp[0]代表该节点不偷时的最大金额,dp[1]代表该节点偷时的最大金额。

        知道了dp数组的构造,我们就能更进一步地得出递归函数的参数和返回值了。根据我们刚刚的分析,是需要子节点两个状态的最大金额数的,因此子节点要返回给我们它的两个状态的值,故返回值就是dp数组,也就是说返回值类型是vector<int>。参数就是当前需要计算的节点的指针。

(2)确定终止条件(dp数组初始化):

        在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回。

(3)确定单层递归的遍历逻辑(递推公式、遍历顺序):

         就是刚刚分析的两种情况:

① 偷父节点,那么左右节点一定都不偷,那么父节点的最大金额就是自身金额+左右节点不偷的最大金额的和。

② 不偷父节点,那么左右节点可偷可不偷,那么父节点的最大金额就是左右节点偷或者不偷的最大金额的和。

        根据这两种情况的分析,遍历顺序就可以很容易地确定为后序遍历的顺序(需要先知道左右节点的值才能计算出父节点的值,故左右中)。

        同时根据这两种情况的分析,可以得到递推公式:(now) dp[1] = (left) dp[0] + (right) dp[0] + cur->val,(now)dp[0] = max((left) dp[0] ,(left) dp[1]) + max((right) dp[0] ,(right) dp[1])。

 (4)确定单层递归逻辑:

        以示例1为例,dp数组状态如下:(注意用后序遍历的方式推导

        最后头结点就是取dp[0]和dp[1]的最大值。

2.代码实现

class Solution {
public:
    vector<int> treeRob(TreeNode * node){
        vector<int> dp(2,0);
        if(node == NULL) return {0,0};
        vector<int> left = treeRob(node->left);
        vector<int> right = treeRob(node->right);
        dp[1] = node->val + left[0] + right[0];
        dp[0] = max(left[0],left[1]) + max(right[0],right[1]);
        return dp;
    }
    int rob(TreeNode* root) {
        vector<int> dp = treeRob(root);
        return max(dp[0],dp[1]);
    }
};

时间复杂度:O(n),n为节点个数,每个节点只遍历了一次

空间复杂度:O(logn)

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

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

相关文章

Axure RP 9 for Mac/win:打造极致交互体验的原型设计神器

在数字化浪潮席卷全球的今天&#xff0c;原型设计作为产品开发的关键环节&#xff0c;其重要性不言而喻。Axure RP 9&#xff0c;作为一款专为设计师和开发者打造的原型设计软件&#xff0c;以其出色的交互设计能力和高效的协作体验&#xff0c;赢得了广大用户的青睐。 Axure …

不同语种下的应用该如何测试?

在测试的过程中&#xff0c;我们有时候会遇到不同语种的页面&#xff0c;通常涉及到国际化&#xff08;Internationalization, i18n&#xff09;和本地化&#xff08;Localization, l10n&#xff09;&#xff0c;在测试的过程中如何保障不同语种软件或应用质量&#xff0c;值得…

xgp会员一年多少钱?xgp一个月多少钱?微软商店xgp会员价格指南

xgp是xbox游戏平台。xgp是类似于steam、epic等&#xff0c;拥有丰富游戏资源的平台。该平 台的全称为“XBox Game Pass”&#xff0c;俗称为“西瓜皮”。xgp是会员订阅模式&#xff0c;开启会员后&#xff0c;所有游戏资源都为你开放。pc版的&#xff0c;第一个月10港币&#x…

1688代采系统:解决全球化采购难题的技术创新

跨境寻源通&#xff08;1688代采系统&#xff09;是面向全球化采购市场的一项技术创新&#xff0c;它旨在帮助企业更高效、便捷和安全地进行跨境采购。以下是这项服务的几个关键特点&#xff1a; 多语言支持&#xff1a;跨境采购往往面临语言障碍问题&#xff0c;而跨境寻源通…

XxlJob外网访问

Xxl-Job使用外网访问 服务注册中心配置 ### web server.port8088 server.servlet.context-path/xxl-job-admin### actuator management.server.base-path/actuator management.health.mail.enabledfalse### resources spring.mvc.servlet.load-on-startup0 spring.mvc.static…

大功率回馈式直流电子负载箱优点和应用

大功率回馈式直流电子负载箱是先进的电力设备&#xff0c;它能够模拟各种复杂的负载情况&#xff0c;对电源进行测试和校准。这种设备具有许多优点&#xff0c;被广泛应用于各种领域。 大功率回馈式直流电子负载箱具有高精度和高稳定性。它能够精确地模拟各种负载情况&#xff…

CISC和RISC

CISC&#xff08;Complex Instruction Set Computer&#xff09;和RISC&#xff08;Reduced Instruction Set Computer&#xff09;是两种不同的计算机架构哲学&#xff0c;它们在指令集的设计、性能优化、硬件复杂度以及应用领域上有着根本的区别。 CISC&#xff08;复杂指令…

皮带机巡检解决方案

在化工行业中、皮带机人工巡检存在的疲劳安全、巡检质量、数据分析等问题&#xff0c;通过以智能巡检机器人为中心的设备生命周期运维管理系统&#xff0c;完成对皮带机的巡检巡逻和排查预警&#xff0c;有效降低人员和设备的安全隐患&#xff0c;更助力企业运维水平和智能化作…

极快!宝藏EI,2-4周录用,接受范围广!

本周投稿推荐 SSCI • 2/4区经管类&#xff0c;2.5-3.0&#xff08;录用率99%&#xff09; SCIE&#xff08;CCF推荐&#xff09; • 计算机类&#xff0c;2.0-3.0&#xff08;最快18天录用&#xff09; SCIE&#xff08;CCF-C类&#xff09; • IEEE旗下&#xff0c;1/2…

后端程序员利用 AI 给网站制作专业 favicon

看看你的 Chrome 浏览器顶部的标签页&#xff0c;每个标签页前面有一个小小的图标&#xff0c;这个就是 favicon&#xff0c;如果你将网页保存到收藏夹&#xff0c;前面也会是这个小图标。这个图标有时候就是网站的 Logo&#xff0c;有时候也不太一样。 上面截图中&#xff0c…

leetcode 每日一题目 (树的直径 +DFS的深刻理解)

如下是题目的简单描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟&#xff0c;感染 将会从值为 start 的节点开始爆发。 每分钟&#xff0c;如果节点满足以下全部条件&#xff0c;就会被感染&…

代码随想录算法训练营第四十九天| LeetCode121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

一、LeetCode121. 买卖股票的最佳时机 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0121.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BA.html 状态&#xff1a;已解决 1.思路 学了双指针的同学可能会下…

LeetCode 热题 100 Day06

矩阵相关题型 Leetcode 48. 旋转图像【中等】 题意理解&#xff1a; 将一个矩阵顺时针旋转90度&#xff0c;返回旋转后的矩阵。 要求&#xff1a; 在原地修改&#xff0c;不借助额外的空间 如果可以使用辅助数组来实现转置,则有 matrix_new[i][j]matrix[j][row-i-1]; 解…

【图片格式转换】ICO、JPG、JPEG、PNG图片格式在线免费转换

ICO、JPG、JPEG、PNG图片格式转换 图片格式转换 https://orcc.online/image 支持ICO、JPG、JPEG、PNG等 主页 https://www.orcc.online 其他工具 pdf在线免费转word文档 https://orcc.online/pdf 时间戳转换 https://orcc.online/timestamp Base64 编码解码 https://orcc…

书生·浦语大模型开源体系(四)作业

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

流水线运行出错排查难?AI 来帮你

“我的企业有几千条流水线&#xff0c;每次流水线运行出错&#xff0c;都要投入不少的技术人员进去排查&#xff0c;需要花费不少的时间。” 遇到这种情况&#xff0c;怎么解决。在 AI 爆火的今天&#xff0c;AI 如何助力 DevOps 效率提升&#xff1f; 云效与阿里云通义大模型…

MPLS LDP浅析及应用场景举例

一、概念 华为ldp是mpls动态的标签分发、存储、控制协议&#xff0c;工作时在2.5层; 默认为只为32位主机路由且存在于路由表中的地址分标签 名词&#xff1a; MPLS domain LSR&#xff1a;Label Switching Router LER&#xff1a;Label Edge Router LSP&#xff1a;Label Swi…

RK3568 学习笔记 : u-boot 千兆网络无法 ping 通PC问题的解决

前言 开发板型号&#xff1a; 【正点原子】 的 RK3568 开发板 使用 虚拟机 ubuntu 20.04 收到单独 编译 RK3568 u-boot 【问题】u-boot 千兆网络无法ping 通&#xff1f;Linux 下千兆网络正常&#xff0c;说明&#xff1a;开发板硬件正常 u-boot 下网络如果通了&#xff0c;…

vr太阳光参数怎么设置,vr快速渲染方法

VR场景中实现逼真的光照效果&#xff0c;太阳光参数的设置尤为关键。真实的太阳光可提升效果图的质感&#xff0c;论VR太阳光参数的设置技巧&#xff0c;包括光源类型选择、光照强度调整、阴影效果优化等多个方面&#xff0c;喜爱一起来看看vr太阳光真实感设置参数吧。 vr太阳光…

Unity 新版输入系统(Input System)

前言 官方教程 注意 新的输入系统需要 Unity 2019.4 和 .NET 4 运行时。它不适用于 .NET 3.5 的项目。 教程版本&#xff1a;Unity 2021.3.26 1. 安装 1.1 打开 Package Manager 导航栏 -> Window -> Package Manager 1.2 安装 Input System 选择 Unity Registry 在列…