代码随想录算法训练营day48 | 198.打家劫舍,213.打家劫舍II,337.打家劫舍III

news2025/1/17 21:35:56

代码随想录算法训练营day48 | 198.打家劫舍,213.打家劫舍II,337.打家劫舍III

  • 198.打家劫舍
    • 解法一:动态规划
  • 213.打家劫舍II
    • 解法一:分别掐头和去尾,动态规划
  • 337.打家劫舍III
    • 解法一:树的递归遍历+动态规划
  • 总结


198.打家劫舍

教程视频:https://www.bilibili.com/video/BV1Te411N7SX
在这里插入图片描述
思路:
1、dp[i]定义:到第 i 间时能拿到的最大金额(此时房间号从0开始)
2、递推公式:当前dp[i]可从两个渠道获得:1、不拿nums[i];2、拿nums[i]。所以递推公式为dp[i]=Math.max(dp[i-1], dp[i-2]+nums[i]);
3、dp数组初始化:dp[0]=nums[0];dp[1]=Math.max(nums[0], nums[1]);(注意nums长度)
4、遍历顺序:当前金额由前面的金额决定,正序遍历房间
5、打印验证

解法一:动态规划

class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[nums.length];
        //初始化
        dp[0]=nums[0];
        if(nums.length<2){
            return dp[0];
        }else{
            dp[1]=Math.max(nums[1],nums[0]);
        }

        for(int j=2;j<dp.length;j++){
            dp[j]=Math.max(dp[j-1], dp[j-2]+nums[j]);
        }

        return dp[dp.length-1];
    }
}

// 优化空间 dp数组只用3格空间 记录与当前计算相关的前两个结果和当前结果
class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[3];
        //初始化
        
        if(nums.length==1){
            return nums[0];
        }else if(nums.length==2){
            return Math.max(nums[1],nums[0]);
            
        }
        dp[0]=nums[0];
        dp[1]=Math.max(nums[1],nums[0]);

        for(int j=2;j<nums.length;j++){
            dp[2]=Math.max(dp[1], dp[0]+nums[j]);
            dp[0]=dp[1];
            dp[1]=dp[2];
        }

        return dp[2];
    }
}

// 统一处理
class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[3];
        for(int i=0;i<nums.length;i++){
            dp[2]=Math.max(dp[1], dp[0]+nums[i]);
            dp[0]=dp[1];        
            dp[1]=dp[2]; 
        }
        return dp[2];
    }
}

213.打家劫舍II

教程视频:https://www.bilibili.com/video/BV1oM411B7xq
在这里插入图片描述
思路:
将环形问题转化为线性问题。本题可将环形问题分解为取第一个元素和不取第一个元素两种情况,考虑的长度为nums.length-1。即掐头和去尾,然后使用上一题的思路解决。

解法一:分别掐头和去尾,动态规划

class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        if (len == 1)return nums[0];
        int num0 = robLiner(nums, nums.length-1, 0);
        int num1 = robLiner(nums, nums.length-1, 1);
        return Math.max(num0, num1);
    }

    public int robLiner(int[] nums, int len,int startIndex) {
        int[] dp = new int[3];
        for(int i=startIndex;i<len+startIndex;i++){
            dp[2]=Math.max(dp[1], dp[0]+nums[i]);
            dp[0]=dp[1];        
            dp[1]=dp[2]; 
        }
        return dp[2];
    }
}

337.打家劫舍III

教程视频:https://www.bilibili.com/video/BV1H24y1Q7sY
在这里插入图片描述
在这里插入图片描述

解法一:树的递归遍历+动态规划

思路:

  1. 对于树来说,当前节点能不能偷,需要依照其左子树根节点和右子树根节点是否被偷来判断,因此需要采用后序遍历(左右中)。
  2. 其次,为了保证计算出当以前节点的为根节点的二叉树能偷的最大金额,需要记录器左右子节点偷和不偷两种状态,因此递归函数的返回值是一个二维数组int[],其中mid[0]表示不偷的最大值,mid[1]表示偷的最大值。
  3. 最后考虑递归逻辑:
    如果是偷当前节点,那么左右孩子就不能偷,mid[1] = left[0]+right[0]+node.val;
    如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以mid[0] = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);
class Solution {
    public int rob(TreeNode root) {
        int[] res = traversal(root);
        return Math.max(res[0], res[1]);
    }

    public int[] traversal(TreeNode node){
        if(node==null)return new int[2];

        int[] left = traversal(node.left);
        int[] right = traversal(node.right);

        int[] mid = new int[2];
        mid[0] = Math.max(left[0],left[1])+Math.max(right[0],right[1]); //不偷node
        mid[1] = left[0]+right[0]+node.val; //偷node
        return mid;
    }
}

总结

对于环的问题,可以通过掐头,去尾转化成两个线性问题来解决。
树形dp要想清楚dp[i]需要想清楚保留什么状态,以及递归逻辑。

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

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

相关文章

基于IF的网站异常流量检测

基于IF的网站异常流量检测 小P&#xff1a;最近渠道好多异常数据啊&#xff0c;有没有什么好的办法可以识别这些异常啊 小H&#xff1a;箱线图、 3 σ 3\sigma 3σ 都可以啊 小P&#xff1a;那我需要把每个特征都算一遍吗&#xff1f;不是数值的怎么算啊&#xff1f; 小H&#…

【2023年4月美赛加赛】Y题:Understanding Used Sailboat Prices 三篇完整论文及代码

【2023年4月美赛加赛】Y题&#xff1a;Understanding Used Sailboat Prices 建25页完整论文及代码 1 题目 2023年MCM 问题Y:理解二手帆船价格 和许多奢侈品一样&#xff0c;帆船的价值也会随着年代和市场条件的变化而变化。所附的“2023_MCM_Problem_Y_Boats.xlsx”文件包括2…

【dfn序+DP】树

把一棵树转化成一个序列有三种方法&#xff1a; dfs序 dfn序&#xff08;时间戳&#xff09; 欧拉序 关于这三者的区别&#xff0c;参考这篇博客&#xff0c;讲的超级好&#xff01; 重谈DFS序、时间戳和欧拉序 - Seaway-Fu - 博客园 (cnblogs.com) 题意&#xff1a; 思路…

【SpringBoot】七:Web服务---Servlet Filter Listener

文章目录 1.Servlet1.1 使用WebServlet创建Servlet1.2 使用编码方式创建Servlet 2.Filter2.1 使用WebFilter创建Filter2.2 使用编码方式创建Filter2.3 Filter排序2.4 使用框架中的 Filter 3. Listener 1.Servlet 1.1 使用WebServlet创建Servlet (1)编写servlet WebServlet(…

数仓建模理论

一、数仓建模理论 &#xff08;一&#xff09;前言 数仓建模就好比是图书馆的书能够分门别类的存放&#xff0c;不仅合理&#xff0c;齐全&#xff0c;而且易于查找。 数据模型就是数据组织和存储方法&#xff0c;强调从业务、数据存取和使用角度合理存储数据。只有将数…

数据结构课程设计——航空客运订票系统

航空客运订票系统 一、引言 1.1 问题的提出 随着时代的发展&#xff0c;智能化生产给社会带来方便与精确&#xff0c;本系统以方便大众&#xff0c;妥善管理机场票务操作为基旨而开发。 本程序以数据结构&#xff08;c语言描述)存储结构进行开发。利用单链表等存储方式为基础…

字节技术面都过了,薪资都谈好了20K*13结果还是被刷了,问HR,原因是。。

面试被拒开端 分享下自己的求职小故事。在一家公司软件测试技术面试已经过了&#xff0c;然后和最终面试官沟通了下&#xff0c;面试官提出来一个薪资数字&#xff0c;我接受了这个提议并和hr同步了这个数字。再然后被拒了&#xff0c;理由就是期望薪资和职级不匹配。我询问后…

鸿蒙元服务万能卡片开发-stage模型和fa模型的卡片区别

一、项目类型 Application&#xff1a; 应用开发 Atomic Service&#xff1a;原子化服务开发 这里选择Empty Ability模板创建项目。 二、Stage模型卡片开发 Api&#xff1a;9 Model&#xff1a;stage Language&#xff1a;ArkTS AppScope &#xff1a;应用的全局配置信息。…

Flutter非常常用的几个布局小控件Center,SizeBox,Divider

Center简介 Center是Flutter中的一个布局小部件&#xff0c;用于将其子部件居中显示在父部件中。 Center的特点 Center小部件具有以下特点&#xff1a; 将子部件在水平和垂直方向上居中显示。默认情况下&#xff0c;Center会尽可能将子部件展开以填充可用空间。如果Center没…

docker未授权rce+docker逃逸复现

docker未授权rcedocker逃逸复现 前言&#xff1a;这段时间跟着bnessy师傅一起打内网&#xff0c;跟着bnessy师傅也学到了很多有用的姿势&#xff0c;这里就来复现几个内网的漏洞&#xff08;大佬轻喷&#xff09; 1、老规矩&#xff0c;还是fscan扫到的漏洞 通过访问&#xff1…

AI突袭景观设计界,这次是真的卷起来了!

目前&#xff0c;AI已经成为内容创作者的灵感来源和效率工具&#xff0c;从设计、内容、视频等创意性工作中&#xff0c;我们看到AI助力下提升了数倍效率&#xff0c;正是如此&#xff0c;也迎来了更多企业的关注&#xff0c;想要将AI融入到各行各业中。 神采PromeAI在不断更新…

Mybatis源码

Mybatis简介 持久层ORM框架&#xff0c;执行sql比较简单&#xff0c;扩展性强&#xff0c;与传统jdbc相比&#xff0c;省去了手写连接的几个步骤&#xff0c;可以通过配置。 节约数据库连接资源&#xff0c;代码易于维护。mybatis 在SqlMapConfig.xml 中配置数据库连接池&#…

【服务器数据恢复】raid离线磁盘上线失败导致分区不识别的数据恢复

服务器数据恢复环境&#xff1a; HP ProLiant DL某系列服务器&#xff0c;三块SAS硬盘组建raid阵列。 上层系统部署有数据库&#xff0c;数据库存放在D分区&#xff0c;备份存放在E分区。 服务器故障&#xff1a; 磁盘故障导致RAID瘫痪&#xff0c;其中一块硬盘状态灯显示红色…

接口测试:Eolink Apikit 和 Postman 哪个更好用?

接口测试&#xff1a;Eolink Apikit 和 Postman 哪个更好用&#xff1f; 很多做服务端开发的同学&#xff0c;应该基本都用过 Postman 来测试接口&#xff0c;虽然 Postman 能支撑日常工作&#xff0c;但是总感觉还是少了点什么&#xff0c;比如需要 Swagger 来维护接口文档&am…

故障分析 | innodb_thread_concurrency 导致数据库异常的问题分析

作者通过分析源码定位数据库异常&#xff0c;梳理参数 innodb_thread_concurrency 设置的注意事项。 作者&#xff1a;李锡超 一个爱笑的江苏苏宁银行数据库工程师&#xff0c;主要负责数据库日常运维、自动化建设、DMP 平台运维。擅长 MySQL、Python、Oracle&#xff0c;爱好骑…

【coding加油站】vue单页面手机商城设计

1、引言 设计结课作业,课程设计无处下手&#xff0c;网页要求的总数量太多&#xff1f;没有合适的模板&#xff1f;数据库&#xff0c;java&#xff0c;python&#xff0c;vue&#xff0c;html作业复杂工程量过大&#xff1f;毕设毫无头绪等等一系列问题。你想要解决的问题&am…

【Python】判断语句 ② ( if else 语句 | if else 语句语法 | Python 中的空格缩进 | 代码示例 )

文章目录 一、if else 语句语法二、Python 中的空格缩进三、代码示例 一、if else 语句语法 if else 语句语法 : if 条件判定:满足条件要执行的代码1满足条件要执行的代码2满足条件要执行的代码3 else:不满足条件要执行的代码1不满足条件要执行的代码2不满足条件要执行的代码3…

佳能打印机删掉又会自动加载的原因及解决方案

驱动人生分析出现佳能打印机删掉又会自动加载的原因可能是因为在系统中&#xff0c;存在着佳能打印机的自动驱动程序。将打印机删除后&#xff0c;系统会自动重新安装该驱动程序&#xff0c;导致打印机重新加载。 特别在一台新的佳能打印机设备到位时&#xff0c;也会出现电脑…

2023自动化测试工具还有什么新鲜事?

我们准备了一份详细指南&#xff0c;介绍了在一个好的测试自动化工具中应该寻找什么&#xff0c;以及哪些工具在 2023 年值得考虑。 尽管手动测试仍然是软件质量保证的强大工具&#xff0c;正如我们在最近关于手动测试与自动测试的长期阅读中再次确立的那样&#xff0c;越来越…

1700页,卷S人的 软件测试《八股文》PDF手册,涨薪跳槽拿高薪就靠它了

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;又得准备面试了&#xff0c;不知道从何下手&#xff01; 不论是跳槽涨薪&#xff0c;还是学习提升&#xff01;先给自己定一个小目标&#xff0c;然后再朝着目标去努力就完事儿了&#xff01; 为了帮大家节约时间&a…