C国演义 [第十二章]

第十二章

  • 打家劫舍
    • 题目理解
    • 步骤
      • dp数组
      • 递推公式
      • 初始化
      • 遍历顺序
    • 代码
  • 打家劫舍II
    • 题目理解
    • 步骤
      • 递推公式
      • 初始化
      • 遍历顺序
    • 代码

打家劫舍

力扣链接

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额

示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)
偷窃到的最高金额 = 1 + 3 = 4

示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)
偷窃到的最高金额 = 2 + 9 + 1 = 12

  • 提示:
    1 <= nums.length <= 100
    0 <= nums[i] <= 400

题目理解

不能在相邻的房屋进行偷窃, 还要求一夜之间能够偷窃的最高金额
那小偷到这个房屋偷还是不偷?

⇒ 偷窃到第 i 个房屋的最大金额 取决于上一次偷窃的是哪个房屋(取决于 第 i -1 个房屋的偷取状态 和 第 i - 2 个房屋的偷取状态)
⇒ 我们可以采用 动态规划的思想

步骤

dp数组

影响因素只有一个, 上一次偷窃的是哪个房屋⇒ dp数组用 一维 的就可以
dp[i] — — [0, i]房屋所得到的最大金额

递推公式

偷窃到第 i 个房屋, 我们能够进行的操作有哪一些:

  1. 所相邻的房屋并没有偷窃, 那我们这个房屋就能进行偷窃 — — dp[i-2] + nums[i]
  2. 所相邻的房屋已经偷窃了, 那我们这个房屋就不能进行偷窃 — — dp[i-1]

最后的结果, 是取两者的最大值⇒ dp[i] = max(dp[i-1], dp[i-2] + nums[i])

初始化

根据递归公式, 我们发现最基础的是 dp[0] 和 dp[1]
dp[0] — — 第一个房屋所能偷窃的最大价值, 那肯定是偷了它 — — dp[0] = nums[0]
dp[1] — — 前两个房屋所能偷窃的最大价值, 那肯定是偷它们之间的最大价值的那个 — — dp[1] = max(nums[0], nums[1])

遍历顺序

根据递归公式, 第 i 天的状态是由前面决定的
⇒ 那么是 由前到后的遍历方向

代码

class Solution {
public:
    int rob(vector<int>& nums) 
    {
        // dp[i] -- -- 区间[0, i]的最大价值
        vector<int> dp(nums.size() + 1, 0);
        dp[0] = nums[0];
        if(nums.size() > 1)
            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];
    }
};


打家劫舍II

力扣链接

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额

示例 1:
输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的

示例 2:
输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4

示例 3:
输入:nums = [1,2,3]
输出:3

  • 提示:
    1 <= nums.length <= 100
    0 <= nums[i] <= 1000

题目理解

这个题目跟上面的很相似, 但是有一个点是不同的:
上面是个线性的, 这个题目是圆形的

那么, 我们能不能用上一个题目的解法来解决这个题目呢?
首先, 先将圆形转化为线性的

在区间[0, i]中, 我们发现:

  • 0为开端, 那么 i 是不能是结尾 (最大是 i - 1结尾)
  • 1为开端, 那么 i 是能是结尾的
    ⇒ 那么我们就可以划分为两个区间:
    [0, i - 1] 和 [1, i]

步骤

递推公式

偷窃到第 i 个房屋, 我们能够进行的操作有哪一些:

  1. 所相邻的房屋并没有偷窃, 那我们这个房屋就能进行偷窃 — — dp[i-2] + nums[i]
  2. 所相邻的房屋已经偷窃了, 那我们这个房屋就不能进行偷窃 — — dp[i-1]

最后的结果, 是取两者的最大值⇒ dp[i] = max(dp[i-1], dp[i-2] + nums[i])

初始化

  • 区间为[0, n - 1]:
    dp[0] = nums[0]
    dp[1] = max(nums[0], nums[1])

  • 区间为[1, n]:
    dp[1] = nums[1]
    dp[2] = max(nums[1], nums[2])

遍历顺序

根据递归公式, 第 i 天的状态是由前面决定的
⇒ 那么是 由前到后的遍历方向

代码

class Solution {
public:
    int rob(vector<int>& nums) 
    {
        // 将环形问题拆分为线性问题
        // 将区间[0, n] 拆分为 包含第一个节点,不包含最后一个节点 和 不包含第一个节点,包含最后一个节点
        // 即将区间[0, n] 拆分为 [0, n-1] 和 [1, n] 两个区间
        // 最后返回两个区间最大值的最大值
        
        if(nums.size() == 1)  return nums[0];
        if(nums.size() == 2)  return max(nums[0], nums[1]);
        
        vector<int> dp(nums.size() + 1, 0);
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        
        for(int i = 2; i < nums.size() - 1; i++)
        {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        int max1 = dp[nums.size() - 2];
        
        dp[1] = nums[1];
        dp[2] = max(nums[1], nums[2]);
        for(int i = 3; i < nums.size(); i++)
        {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        int max2 = dp[nums.size() - 1];
        
        return max(max1, max2);
    }
};


连伟人的一生都充满了那么大的艰辛,一个平凡的人吃点苦又算得了什么呢? — — 路遥

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

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

相关文章

如何保证消息的可靠性+延迟队列(TTL+死信队列+延迟队列)

目录 1.如何保证消息的可靠性 1.1.消息的可靠投递 confirm机制 return机制 1.2.如何保证消息在队列中不丢失 1.3.确保消息能可靠的被消费掉 2.延迟队列 2.1.TTL 2.2.死信队列 2.3.延迟队列 3.如何防止消费者重复消费消息 1.如何保证消息的可靠性 1.1.消息的可靠投递…

VMware扩展磁盘提示:在部分链上无法执行所调用的函数。请打开父虚拟磁盘

VMware扩展磁盘提示&#xff1a;在部分链上无法执行所调用的函数。请打开父虚拟磁盘 在为VMware中的虚拟机扩展磁盘时提示&#xff1a;在部分链上无法执行所调用的函数。请打开父虚拟磁盘。 出现这个问题是因为你先前创建过快照&#xff0c;但是快照删除时候&#xff0c;残余文…

【数据结构】链表及无头单向非循环链表实现

目录 1.顺序表的问题 2.链表的概念、结构及分类 3.无头单向非循环链表实现 3.1创建节点 3.2头插数据 3.3头删数据 3.4尾插 3.5尾删 3.6链表销毁 3.7查找一个元素 3.8在pos之前插入 3.9在pos之后插入 3.10删除pos位置 3.11删除pos之后的位置 1.顺序表的问题 顺…

Linux操作系统——第五章 进程信号

目录 信号概念 用kill -l命令可以察看系统定义的信号列表 信号处理常见方式概览 产生信号 1. 通过终端按键产生信号 2. 调用系统函数向进程发信号 3. 由软件条件产生信号 4. 硬件异常产生信号 阻塞信号 1. 信号其他相关常见概念 2. 在内核中的表示 3. sigset_t 4.…

C语言——指针详解(进阶)

轻松学会C语言指针 一、字符指针二、数组指针2.1 数组指针的定义2.2 &数组名VS数组名2.3 数组指针的使用 三、指针数组四、数组参数和指针参数4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参 五、函数指针六、函数指针数组七、指向函数指针数组的指针八…

Kubernetes - HPA-VPA - metrics介绍和安装 - HPA实验

目录 参考文章&#xff1a;(97条消息) Kubernetes-自动扩展器HPA、VPA、CA_hpa vpa_SRE运维充电站的博客-CSDN博客 HPA VPA 官方网址&#xff1a;autoscaler/vertical-pod-autoscaler at master kubernetes/autoscaler GitHub HPA和VPA进行扩缩容的区别&#xff1a; me…

小研究 - 面向 Java 的高对抗内存型 Webshell 检测技术(四)

由于 Web 应用程序的复杂性和重要性, 导致其成为网络攻击的主要目标之一。攻击者在入侵一个网站后, 通常会植入一个 Webshell, 来持久化控制网站。但随着攻防双方的博弈, 各种检测技术、终端安全产品被广泛应用, 使得传统的以文件形式驻留的 Webshell 越来越容易被检测到, 内存…

《TCP IP网络编程》第七章

第七章&#xff1a;优雅的断开套接字的连接 TCP 的断开连接过程比建立连接更重要&#xff0c;因为连接过程中一般不会出现大问题&#xff0c;但是断开过程可能发生预想不到的情况。因此应该准确掌控。所以要掌握半关闭&#xff08;Half-close&#xff09;&#xff0c;才能明确断…

windows10 搭建hadoop环境,并且使用hadoop命令

hadoop 环境创建 1. 八、window搭建spark IDEA开发环境 按照步骤安装完 2. windows下安装和配置hadoop 配置环境变量&#xff0c;注意JAVA_HOME路径&#xff0c;修改后&#xff0c;重启电脑&#xff0c;不重启容易报错&#xff01;&#xff01;&#xff01; ​ 新建dat…

数据结构(王道)——数据结构之 二叉树

一、数据结构之 二叉树概念&#xff1a; 特殊的二叉树结构&#xff1a; 满二叉树完全二叉树 二叉排序树 平衡二叉树 二叉树基本概念总结&#xff1a; 二、二叉树的常用性质&#xff1a; 1、叶子结点比二分支结点多一个

Kubernetes - kubeadm部署

Kubernetes - kubeadm部署 1 环境准备1.1 在各个节点上配置主机名&#xff0c;并配置 Hosts 文件1.2 关闭防护墙&#xff0c;禁用selinux&#xff0c;关闭swap1.3 配置免密登录1.4 配置内核参数1.5 配置br_netfilter 2. 安装K8s2.1 安装docker(各节点)2.2 安装K8s组件(各节点)2…

走进Vue2飞入Vue3

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; Vue ✨特色专栏&#xff…

“掌握更多的快速排序技巧:三路划分、双路快排和非递归的深入理解”

快速排序是一种基于分治思想的排序算法&#xff0c;它能够以极快的速度将一个乱序的数组重新排列成有序的序列。不仅如此&#xff0c;快速排序还具有简洁的实现代码和良好的可扩展性&#xff0c;成为最受欢迎的排序算法之一。接下来&#xff0c;让我带你了解一下它的魅力吧&…

【Matlab】智能优化算法_麻雀搜索算法SSA

【Matlab】智能优化算法_麻雀搜索算法SSA 1.背景介绍2.数学模型3.文件结构4.伪代码5.详细代码及注释5.1 Get_Functions_details.m5.2 main.m5.3 SSA.m 6.运行结果7.参考文献 1.背景介绍 麻雀通常是群居的鸟类&#xff0c;有很多种类。它们分布在世界的大部分地区&#xff0c;喜…

Http host 标头攻击

一、什么是http host 标头攻击 HTTP Host 标头攻击是一种网络安全攻击技术&#xff0c;利用了 HTTP 协议中的 Host 标头字段的漏洞。Host 标头字段用于指定客户端请求的目标主机名或域名。 攻击者可以通过构造恶意的 HTTP 请求&#xff0c;伪造或篡改 Host 标头字段的值&#x…

高精尖领域数据暴增,分布式存储渐当大任

近年来&#xff0c;数据存储市场“最靓的仔”无疑就是分布式存储。 大模型火了之后&#xff0c;围绕Chat的应用也越来越多&#xff0c;通过AI生成图片、报表、音视频的应用比比皆是。众所周知&#xff0c;要想训练出一个有学习能力的、可理解的、响应迅速的大模型应用&#xf…

[NGINX] NGINX下载、安装编译、启动检查停止命令

一、NGINX 下载 mkdir -p /soft/nginx cd /soft/nginx wget https://nginx.org/download/nginx-1.21.6.tar.gz二、下载相关依赖 ①在线安装依赖&#xff1a; yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel ②下载依赖到本地安装依赖&#xff1a; y…

InsCode Stable Diffusion使用教程【InsCode Stable Diffusion美图活动一期】

记录一下如何使用 InsCode Stable Diffusion 进行 AI 绘图以及使用感受。 一、背景介绍 目前市面上比较权威&#xff0c;并能用于工作中的 AI 绘画软件其实就两款。一个叫 Midjourney&#xff08;简称 MJ&#xff09;&#xff0c;另一个叫 Stable Diffusion&#xff08;简称 …

使用 uiautomator2+pytest+allure 进行 Android 的 UI 自动化测试

目录 前言&#xff1a; 介绍 pytest uiautomator2 allure 环境搭建 pytest uiautomator2 allure pytest 插件 实例 初始化 driver fixture 机制 数据共享 测试类 参数化 指定顺序 运行指定级别 重试 hook 函数 断言 运行 运行某个文件夹下的用例 运行某…

RabbitMQ保证消息的可靠投递,Java实现RabbitMQ消息的可靠投递,Springboot实现RabbitMQ消息的可靠投递

文章目录 一、RabbitMQ消息可靠性概述1、引出问题2、RabbitMQ消息可靠性保证的四个环节 二、保证生产者消息发送到RabbitMQ服务器1、服务端确认&#xff1a;Transaction模式&#xff08;1&#xff09;JavaAPI&#xff08;2&#xff09;springbootAPI 2、服务端确认&#xff1a;…