代码随想录训练营第48天|LeetCode 198.打家劫舍、213.打家劫舍II、 337.打家劫舍III

news2024/11/18 8:26:55

参考

代码随想录

题目一:LeetCode 198.打家劫舍

  1. 确定dp数组下标及其含义
    dp[i]:考虑下标i(包括i)以内的房屋,可以偷窃的最大金额为dp[i]。
  2. 确定递推公式
  • 如果当前的第i个房间不偷,那么dp[i] = dp[i-1].
  • 如果当前的第i个房间要偷,那么只能不偷第i-1个房间,所以dp[i] = dp[i-2] + nums[i].

最终要得到最大金额,因此dp[i] = max(dp[i-1],dp[i-2]+nums[i]).

  1. 初始化dp数组
dp[0] = nums[0];
dp[1] = max(nums[0],nums[1]);
  1. 确定遍历顺序
    dp[i]要由dp[i-1]和dp[i-2]来确定,因此要从前往后遍历。
  2. 举例推导dp数组
    在这里插入图片描述
    完整的代码实现如下:
class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size() == 1)    return nums[0];
        vector<int> dp(nums.size(), 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-1],dp[i-2] + nums[i]);
        }
        return dp.back();
    }
};

题目二:LeetCode 213.打家劫舍II

这个题在“198.打家劫舍”的基础上加入了环,如果没有环,每间房间只需要考虑上一间房间是否偷过,加入环之后,“最后”一间房间还要考虑第一间房间是否偷过。但可以将问题转化为上一个题,因为开头和末尾房间只能偷一间,因此分为两种情况,一种是不包含末尾房间,一种是不包含开头房间,最后的结果是这两种的最大值。这两种情况和上一个题完全一样。
代码实现如下:

class Solution {
public:
    int robRange(vector<int>& nums, int start, int end)
    {
        if(start == end) return nums[start];
        vector<int> dp(end - start + 1);
        dp[0] = nums[start];
        dp[1] = max(nums[start],nums[start + 1]);
        for(int i = 2; i <= end - start; i++)
            dp[i] = max(dp[i-1],dp[i-2] + nums[start+i]);
        return dp.back();
    }

    int rob(vector<int>& nums) {
        if(nums.size() == 1)    return nums[0];
        int val1 = robRange(nums,0,nums.size()-2);
        int val2 = robRange(nums,1,nums.size()-1);
        return max(val1,val2);
    }
};

题目三:LeetCode 337.打家劫舍III

  1. 确定递归函数的参数和返回值
    这里我们要求一个节点 偷与不偷的两个状态所得到的金钱,那么返回值就是一个长度为2的数组。其实这里的返回数组就是dp数组。
    所以dp数组(dp table)以及下标的含义:下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。
vector<int> robTree(TreeNode* cur);
  1. 确定终止条件
    在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回。这里相当于dp数组的初始化。
if (cur == NULL) return vector<int>{0, 0};
  1. 确定遍历顺序
    首先明确的是使用后序遍历。 因为通过递归函数的返回值来做下一步计算。
    通过递归左节点,得到左节点偷与不偷的金钱。
    通过递归右节点,得到右节点偷与不偷的金钱。
// 下标0:不偷,下标1:偷
vector<int> left = robTree(cur->left); // 左
vector<int> right = robTree(cur->right); // 右
  1. 确定单层递归逻辑
  • 如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; (如果对下标含义不理解就在回顾一下dp数组的含义)
  • 如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);
    最后当前节点的状态就是{val2, val1}; 即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}
// 偷cur
int val1 = cur->val + left[0] + right[0];
// 不偷cur
int val2 = max(left[0], left[1]) + max(right[0], right[1]);
return {val2, val1};
  1. 举例推导dp数组
    在这里插入图片描述
    完整的代码实现如下:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int rob(TreeNode* root) {
        vector<int> result = robTree(root);
        cout << result[0] << "  " << result[1] << endl;
        return max(result[0], result[1]);
    }
    // 长度为2的数组,0:不偷,1:偷
    vector<int> robTree(TreeNode* cur) {
        if (cur == NULL) return vector<int>{0, 0};
        vector<int> left = robTree(cur->left);
        vector<int> right = robTree(cur->right);
        // 偷cur,那么就不能偷左右节点。
        int val1 = cur->val + left[0] + right[0];
        // 不偷cur,那么可以偷也可以不偷左右节点,则取较大的情况
        int val2 = max(left[0], left[1]) + max(right[0], right[1]);
        return {val2, val1};
    }
};

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

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

相关文章

干货收藏 |关键词优化攻略!(附11款关键词检索工具)

关键字搜索是买家查找产品的方式&#xff0c;一个高质量的关键词可以帮助卖家快速增加曝光率。简而言之&#xff0c;利用好关键词机理&#xff0c;能让我们的产品产生更有利的排名因素。 那如何找到合适的关键字&#xff0c;设置关键字时应该注意什么&#xff1f; 今天从产品的…

libcrypto-1_1.dll丢失,要怎么处理?

一般出现这个libcrypto-1_1.dll丢失的问题&#xff0c;我看绝大部分都是出在刺客信条这边的人&#xff0c;很多人吐槽 在运行刺客信条3游戏的时候遇到提示缺少libcef.dll文件的问题。其实遇到这问题还是比较好解决的。 libcrypto-1_1.dll丢失的处理方法 第一种&#xff0c;首…

云存储--1

背景 这一板块主要是讲诉云计算中的存储板块。 那么云存储主要分为三大类&#xff1a;块存储、文件存储、对象存储。 那么&#xff0c;这一章我们来了解一下什么是块存储&#xff0c;以及块存储在云计算当中的使用场景。 1、 什么是块存储&#xff1f; 我们来思考一个场景&a…

Spring Boot集成MyBatis

1.整合Durid数据源 1、引入Jar包 2.application.yml配置 3.读取配置类DruidConfig 总结&#xff1a;其实没有必要一个个手动去配置&#xff0c; druid 启动starter druid 自动配置类 2.整合MyBatis 2.1生成MyBatis代码: pom.xml generatorConfig.xml 运行插件—…

java计算机毕业设计ssm余庆金阳驾校管理系统75wh9(附源码、数据库)

java计算机毕业设计ssm余庆金阳驾校管理系统75wh9&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#…

看完这篇,轻松编写Markdown

攻城狮为什么要会Markdown Markdown是什么 Markdown是一种轻量级标记语言&#xff0c;创始人为约翰格鲁伯&#xff08;John Gruber&#xff09;。它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成有效的 XHTML&#xff08;或者HTML&#xff09;文档。这种语…

【网络攻防】Linux提权(待更)

Linux提权 文章目录Linux提权1.利用suid提权&#xff08;1&#xff09;如何设置suid&#xff08;2&#xff09;如何找到设置了suid的程序&#xff08;3&#xff09; suid提权2.利用环境变量提权&#xff08;1&#xff09;创建拥有 suid 权限的程序&#xff08;2&#xff09;劫持…

vue innerHTML 绑定单击事件不生效

在使用 vue时候对 innerHTML进行绑定单击事件&#xff0c;绑定后事件不生效 原代码 div.innerHTML "<el-button sizemini typetext clickhandleUpdate1("JSON.stringify(warnCntItem)") stylecolor: #f56c6c> "warnCntItem.warnCnt"</el-b…

【云计算与大数据技术】分布式协同系统Chubby锁、ZooKeeper在HDFS中的使用讲解(图文解释 超详细)

阿里云Kuafa RPC系统 夸父(Kuafu)是飞天平台内核中负责网络通信的模块&#xff0c;它提供了一 个 RPC 的接口 , 简化编写基于网络的分布式应用 夸父的设计目标是提供高可用(724小时)、大吞吐量(Gigabyte)、高效率、易用(简明 API、多种协议和编程接口)的 RPC服务 Hadoop IPC…

【软件测试】资深测试的建议。初入测试行的小伙伴,准备起航吧......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 大部分初级的岗位&a…

Java面试题总结-抽象类和接口的区别

抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。 从设计层面来说&#xff0c;抽象类是对类的抽象&#xff0c;是一种模板设计&#xff0c;接口是行为的抽象&#xff0c;是一种行为的规范。 想要了解抽象类和接口的区别&#xff0c;我们首先要想清楚抽象类和接口的相…

Word控件Spire.Doc 【超链接】教程(3):在C#中查找word文档中的超链接

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

服务端监控工具:Nmon使用方法

目录&#xff1a;导读 一、认识nmon 二、检查安装环境 三、nmon下载安装 四、运行nmon 五、采集数据 总结 写在最后 一、认识nmon 1、简介 nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具&#xff0c;它能在系统运行过程中实时地捕捉系统资源的使用情…

再学C语言1:开发环境

重新把C语言梳理一遍&#xff0c;学习在VSCode中进行C语言编程。 因此第一步是把环境配置起来。 步骤一&#xff1a;下载、安装VSCode 官网下载即可&#xff0c;地址&#xff1a;https://code.visualstudio.com/Visual Studio Code is a code editor redefined and optimize…

Docker:docker安装nginx

目录 一、容器之间相互通信 1、两个容器在同一网段 2、两个容器在不同网段 二、安装Nginx 1.nginx是什么 2. 安装nginx 三、部署前端项目 2.nginx.conf讲解 一、容器之间相互通信 1、两个容器在同一网段 查看docker中已安装的所有网络 docker network ls 查看自定义网络myn…

springboot+java农家乐系统-住宿-美食-活动vue

目 录 摘 要 1 Abstract 1 1 系统概述 4 1.1 概述 4 1.2课题意义 4 1.3 主要内容 4 2 系统开发环境 5 2.1 JAVA简介 5 2.2 B/S架构 5 2.3系统对MySQL数据库的两种连接方式 6 2.4 MySql数据库 6 3 需求分析 7 3.1技术可行性&#xff1a…

交互式分割: Interactive Object Segmentation with Inside-Outside Guidance

论文&#xff1a;https://ieeexplore.ieee.org/document/9157733 代码&#xff1a; https://github.com/shiyinzhang/Inside-Outside-Guidance 思想概述 作者利用画取一个BBOX 作为前、背景的快速区分&#xff0c;同时在BBOX内进行进行动手动在前景对象上进行交互&#xff0c…

安装博客,论坛

准备环境 防火墙&#xff0c;selinux关掉 [rootboke ~]#yum -y install mariadb mariadb-server mariadb-libs php php-mysql php-gd php-fpm php-cli gd httpd 安装lamp环境 [rootboke ~]# systemctl start httpd mariadb 启动httpd和mariadb 搭建博客 配数据库 [root…

毕业设计-BP神经网络的房地产价值评估研究

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

(已更新)BGS本地局域网视频源码

BGS本地局域网视频源码是PHP的&#xff0c;TP5.1 数据库和伪静态设置在压缩包&#xff0c;记得设置运行目录为public 数据库配置请到 config\database.php中修改 只支持MP4&#xff0c;上传后观看时候会自动进行转换为m3u8,调用的是FFmpeg&#xff0c;主要就是为了研究php使用F…