「动态规划」打家劫舍的变形题,你会做吗?

213. 打家劫舍 IIicon-default.png?t=N7T8https://leetcode.cn/problems/house-robber-ii/description/

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,今晚能够偷窃到的最高金额。

  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。


本题在打家劫舍问题的基础上,加上了首尾相连的条件。解决本题的关键在于如何处理首尾相连的条件。假设有n个房屋。这里,我们根据偷不偷0位置的房屋,进行分类讨论:

  • 如果偷了0位置的房屋,那么就不能偷1位置和n - 1位置的房屋,此时问题转换为:房屋区间为[2, n - 2]的不含首位相连条件的打家劫舍问题。
  • 如果不偷0位置的房屋,此时问题转换为:房屋区间为[1, n - 1]的不含首位相连条件的打家劫舍问题。

而最终的结果,应该是这两种情况的较大值。好了,此时我们只需要解决不含首尾相连条件的打家劫舍问题。我们用动态规划的思想来解决这个问题,以下的讨论都不含首尾相连的条件。

确定状态表示:根据经验和题目要求,我们用dp[i]表示,考虑完i位置的房屋后,此时能偷到的最高金额。这又细分为:

  • 用f[i]表示:必须偷i位置的房屋,此时能偷到的最高金额
  • 用g[i]表示:不能偷i位置的房屋,此时能偷到的最高金额

推导状态转移方程:我们分别考虑2种情况中最近的一步,即是否偷i - 1位置的房屋。

  • 考虑f[i],由于必须偷i位置的房屋,所以不能偷i - 1位置的房屋。偷完i位置的房屋之后,能偷到的最高金额,就等于不能偷i - 1位置的房屋之后能偷到的最高金额加上i位置的房屋的金额,即f[i] = g[i - 1] + nums[i]。
  • 考虑g[i],由于不能偷i位置的金额,所以此时能偷到的最高金额就等于考虑完i - 1位置的房屋后能偷到的最高金额。由于不确定是否偷i - 1位置的房屋,所以结果是偷或者不偷i - 1位置的房屋这2种情况中,能偷到的最高金额的较大值,即g[i] = max(f[i - 1], g[i - 1])。

综上所述,f[i] = g[i - 1] + nums[i],g[i] = max(f[i - 1], g[i - 1])

初始化:根据状态转移方程,在填写f[0]和g[0]时,会发生越界访问,所以要对其初始化。

  • 如果必须偷0位置的房屋,那么此时能偷到的最高金额就是0位置的房屋的金额,即f[0] = nums[0]。
  • 如果不能偷0位置的房屋,那么此时能偷到的最高金额就是0,即g[0] = 0。

综上所述:f[0] = nums[0],g[0] = 0

填表顺序:根据状态转移方程,f[i]依赖于g[i - 1],g[i]依赖于f[i - 1]和g[i - 1],所以应从左往右同时填f表和g表

返回值:我们要求的是考虑完n - 1位置的房屋后,此时能偷到的最高金额,由于并不确定是否偷n - 1位置的房屋,所以结果是偷或者不偷n - 1位置的房屋这2种情况中,能偷到的最高金额的较大值,即max(f[n - 1], g[n - 1])

细节问题:回归题目本身。假设对于没有首尾相连条件的打家劫舍问题中,房屋区间是[left, right],能偷到的最高金额是rob(nums, left, right)。那么,最终的结果就是文章开头提到的2种情况的较大值,即max(nums[0] + rob(nums, 2, n - 2), rob(nums, 1, n - 1))。注意到下标几乎覆盖了整个nums数组,所以为了简单起见,我们把dp表的规模设置成和nums相同,即1 x n。此时,应初始化f[left] = nums[left],g[left] = 0,填表时应从left + 1位置开始一直填到right位置,最终应该返回max(f[right], g[right])

时间复杂度:O(N),空间复杂度:O(N)。

class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();// 偷或者不偷0位置的房屋,这2种情况的较大值return max(nums[0] + rob(nums, 2, n - 2), rob(nums, 1, n - 1));}private:// 不含首尾相连条件的打家劫舍问题,房屋区间为[left, right]int rob(vector<int>& nums, int left, int right) {// 区间不存在if (left > right) {return 0;}int n = nums.size();// 创建dp表vector<int> f(n);auto g = f;// 初始化f[left] = nums[left];// 填表for (int i = left + 1; i <= right; i++) {f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1], g[i - 1]);}// 返回结果return max(f[right], g[right]);}
};

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

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

相关文章

Spring RestClient报错:400 Bad Request : [no body]

我项目采用微服务架构&#xff0c;所以各服务之间通过Spring RestClient远程调用&#xff0c;本来一直工作得好好的&#xff0c;昨天突然发现远程调用一直报错&#xff0c;错误详情如下&#xff1a; org.springframework.web.client.HttpClientErrorException$BadRequest: 400…

使用 Vue 官方脚手架初始化 Vue3 项目

Vite 官网&#xff1a;https://cn.vitejs.dev/ Vue 官网&#xff1a;https://vuejs.org/ Vue 官方文档&#xff1a;https://cn.vuejs.org/guide/introduction.html Element Plus 官网&#xff1a;https://element-plus.org/ Tailwind CSS 官网&#xff1a;https://tailwindcss.…

LocalDate和Date有什么区别?两者如何转换?

LocalDate与Date 在Java中&#xff0c;LocalDate和Date是用来处理日期的两种不同的类。 区别&#xff1a; Date是Java早期的日期类&#xff0c;它包含了日期和时间的信息。但是在Java 8之后&#xff0c;Date类被标记为过时的&#xff0c;推荐使用新的日期时间API&#xff0c;…

Codeforces Round 951 (Div. 2)C. Earning on Bets

Problem - C - Codeforces 合理的答案&#xff1a; 求出 k1 ~ kn 的最小公倍数lcm&#xff0c;如果 lcm/k1 lcm/k2 ... lcm/kn < lcm 即符合题意。 左边之和为我们付的总钱数&#xff0c;右边才是每次选择得到的钱数(都为lcm)。 直接拿1e9检查是否可以分即可&#xff…

基于Django+MySQL的智慧校园系统

此项目基于Django MySQL HTML CSS JS jQuery bootstrap实现的功能有 学生管理部门管理代办清单管理校园论坛校园医疗服务校园看点校园生活助手常用功能入口 1. 一些注意点 1. 页面body会自动有一些边界距&#xff0c;处理方法&#xff1a; <head><style>b…

你还在纠结U盘怎么选吗?小白带你来看

前言 2024年的618活动已经开始了&#xff0c;这个活动买电子产品着实是比其他时间要便宜很多。 前几天小白的一个好朋友问我&#xff1a;U盘该怎么选&#xff1f; 呃&#xff0c;本来是想写“老朋友”的&#xff0c;结果她愣是要我改成“好朋友”。 行吧&#xff0c;那就好朋…

kmp算法c++

kmp算法通过next数组使查找失败时减少跳转后比较的次数来优化字符串查找&#xff0c;next数组存储了前缀和后缀相同的位置信息&#xff0c;类似动规&#xff0c;可以存储查找数组的信息来防止重复查找&#xff0c;最终复杂度可以达到O&#xff08;nm&#xff09;。 以t“abcab…

车载电子电气架构 --- 车载信息安全

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

Vite - 开发初体验,以及按需导入配置

目录 开始 创建一个 Vite 项目 项目结构 /src/main.js index.html package.json vite.config.js Vite 项目中使用 vue-router Vite 组件的“按需引入” 传统的方式引入一个组件 传统方式引入带来的问题 解决办法&#xff08;配置 按需引入 插件&#xff09; 示例&…

嵌入式学习——Linux高级编程复习(线程)——day40

1. 线程 1.1 定义 线程是一个轻量级的进程 是一个任务被创建、调度、消亡的过程 1.2 线程和进程的区别与联系 1. 线程是CPU任务调度的最小单元 2. 进程是操作系统资源分配的最小单元 3. 线程&#xff08;Thread&#xff09;是操作系统能够进行运算调度的最小单位…

OpenFeign远程接口调用使用公共模块出现的错误

今天在使用openfeign和sentinel实现fallback服务降级时遇到找不到类型的异常 检查代码发现没有错误&#xff0c;EnableFeignClients也在启动类上标注了 错误信息&#xff1a;A component required a bean of type com.zxc.cloud.apis.PayFeignSentinelApi that could not be f…

《精通ChatGPT:从入门到大师的Prompt指南》第9章:实战练习

第9章&#xff1a;实战练习 9.1 Prompt练习题 在本节中&#xff0c;我们将提供一系列练习题&#xff0c;旨在帮助读者通过实际操作提升使用ChatGPT的能力。这些练习题涵盖了从基础到高级的不同难度级别&#xff0c;并针对各种应用场景设计&#xff0c;确保读者能够在实际使用…

基于Springboot + vue实现的火锅店管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

私有云和多云管理平台 | Cloudpods v3.11.4 正式发布

本次 3.11.4 更新亮点为&#xff1a;系统镜像引入社区镜像&#xff0c;用户可以一键导入各主流开源操作系统镜像&#xff0c;方便用户上手使用。持续迭代共享 LVM&#xff0c;支持快照&#xff0c;主备机等特性&#xff0c;修复迁移删除镜像缓存等 BUG。 功能优化 【费用】费…

【调度算法】Boltzmann选择

Boltzmann选择是一种基于Boltzmann分布的选择策略&#xff0c;主要用于进化算法中的个体选择过程。它通过模拟物理系统的热平衡状态来调节个体选择的概率&#xff0c;能够在进化初期保持种群多样性&#xff0c;并在进化后期集中选择适应度高的个体。 Boltzmann选择的表达式 B…

EON安装ASE Interface

安装 测试系统ubuntu。如果你python2和python3总是纠缠不清&#xff0c;可以sudo apt install python-is-python3直接解决。 经检查&#xff0c;我PC的 python地址为&#xff1a; /usr/include/python3.8/ pybind11地址为&#xff1a; /usr/include/pybind11/ 已确认python…

web前端的MySQL:跨领域之旅的探索与困惑

web前端的MySQL&#xff1a;跨领域之旅的探索与困惑 在数字化浪潮的推动下&#xff0c;web前端与MySQL数据库似乎成为了两个不可或缺的领域。然而&#xff0c;当我们将这两者放在一起&#xff0c;尝试探索web前端与MySQL之间的交互与关联时&#xff0c;却发现这是一次充满困惑…

AE电源pinnacle软件新款老款二款软件

AE电源pinnacle软件新款老款二款软件

C++从入门到精通(最详细教程,12万总结,带你掌握c++知识,涵盖大量知识点)

目录 一、面向对象的思想 二、类的使用 1.类的构成 2.类的设计 三、对象的基本使用 四、类的构造函数 1.构造函数的作用 2.构造函数的特点 3.默认构造函数 3.1.合成的默认构造函数 3.2.手动定义的默认构造函数 四、自定义的重载构造函数 五、拷贝构造函数 1.手动…

联合体和枚举<C语言>

导言 在C语言中除了结构体外&#xff0c;联合体和枚举也是自定义类型&#xff0c;联合体主要用于节省空间&#xff0c;在同一块内存存储多种类型的数据&#xff0c;而枚举可以提高代码的可读性、可维护性。 联合体&#xff08;union&#xff09; 它还有个更容易理解的名字&…