破解打家劫舍:动态规划与二分查找的高效算法

目录

198. 打家劫舍

 解法一:一维动态规划

 解法二:二维动态规划

213. 打家劫舍 II

思路分析

代码实现

337. 打家劫舍 III

思路分析

代码实现

2560. 打家劫舍 IV

思路分析 

参考博客


198. 打家劫舍

如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 ,求今晚能够偷窃到的最高金额。

 解法一:一维动态规划

class Solution {public int rob(int[] nums) {if (nums == null || nums.length == 0) {return 0;}int n =  nums.length;int dp[] = new int[n]; if (n == 1) {return nums[0];}dp[0] = nums[0]; dp[1] =  Math.max(nums[0],nums[1]); for(int i=2;i<n;i++){// 不偷这个房子,那么总金额就是偷到前一个房子为止的最大金额,即 dp[i-1]。// 偷这个房子,那么总金额就是这个房子的金额加上偷到前前一个房子为止的最大金额,即 nums[i] + dp[i-2]。dp[i] = Math.max(dp[i-1], nums[i] + dp[i-2]);}return dp[n-1];}
}

 解法二:二维动态规划

参考这篇博客的方法三LeetCode122之股票买卖的最好时机(相关话题:动态规划,记忆搜索,状态机,贪心算法)_最适合买入股票算法题-CSDN博客

class Solution {public int rob(int[] nums) {int n =  nums.length;//dp[i][0]表示不偷第i个房间,dp[i][1]表示偷第i个房间int dp[][] = new int[n][2]; dp[0][0] = 0; dp[0][1] = nums[0]; for(int i=1;i<n;i++){dp[i][0] =  Math.max(dp[i-1][0] , dp[i-1][1]);dp[i][1] =  dp[i-1][0] + nums[i];}return Math.max(dp[n-1][0],dp[n-1][1]);}
}

213. 打家劫舍 II

这个地方所有的房屋都 围成一圈 ,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 , 求今晚能够偷窃到的最高金额。

思路分析

  1. 第一次考虑时,我们假设偷了第一间房屋,因此不能偷最后一间房屋。这样,我们就只考虑从第一间房屋到倒数第二间房屋的数组范围,即 nums[0] 到 nums[n-2]。
  2. 第二次考虑时,我们假设不偷第一间房屋,这样就可以偷最后一间房屋。这时,我们考虑的数组范围是从第二间房屋到最后一间房屋,即 nums[1] 到 nums[n-1]。

代码实现

基于(Python)


class Solution:def rob(self, nums: List[int]) -> int:# 辅助函数,用于处理不成环的情况def rob_linear(houses):n = len(houses)if n == 1:return houses[0]if n == 2:return max(houses[0], houses[1])dp = [0] * ndp[0] = houses[0]dp[1] = max(houses[0], houses[1])for i in range(2, n):dp[i] = max(dp[i-1], dp[i-2] + houses[i])return dp[-1]# 如果房屋数量小于3,直接返回最大金额的房子n = len(nums)if n == 1:return nums[0]if n == 2:return max(nums[0], nums[1])# 第一次考虑时,我们假设偷了第一间房屋,因此不能偷最后一间房屋。这样,我们就只考虑从第一间房屋到倒数第二间房屋的数组范围,即 nums[0] 到 nums[n-2]。#第二次考虑时,我们假设不偷第一间房屋,这样就可以偷最后一间房屋。这时,我们考虑的数组范围是从第二间房屋到最后一间房屋,即 nums[1] 到 nums[n-1]。return max(rob_linear(nums[:-1]), rob_linear(nums[1:]))

337. 打家劫舍 III

root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

思路分析

  • 如果偷当前节点,那么子节点就不能偷
  • 如果不偷当前节点,那么子节点可以偷也可以不偷,取决于哪种选择更优
  • 如果函数只返回一个值可能会超时,需要引入缓存,可以考虑函数分别返回访问当前节点的最大收益,和不访问当前节点最大收益数组

代码实现

只有一个返回值加缓存的实现

class Solution {public int rob(TreeNode root) {// 使用HashMap来存储节点在被访问和未被访问时的最大值Map<TreeNode, Integer>[] memo = new Map[2];memo[0] = new HashMap<>();  // 不偷当前节点的情况memo[1] = new HashMap<>();  // 偷当前节点的情况int maxProfit =  Math.max(helpRob(root,1,memo), helpRob(root,0,memo));return maxProfit;}private int helpRob(TreeNode root, int canRob, Map<TreeNode, Integer>[] memo) {if(root==null){return 0;}// 检查缓存是否已有结果if (memo[canRob].containsKey(root)) {return memo[canRob].get(root);}int maxProfit = 0;if(canRob==1){// 如果偷当前节点,那么子节点就不能偷maxProfit =  Math.max(maxProfit ,root.val + helpRob(root.left,0,memo) + helpRob(root.right,0,memo));}else{int temp1 =  helpRob(root.left,0,memo);int temp2 =  helpRob(root.left,1,memo);int temp3 =  helpRob(root.right,0,memo);int temp4 =  helpRob(root.right,1,memo);// 如果不偷当前节点,那么子节点可以偷也可以不偷,取决于哪种选择更优maxProfit = Math.max(temp1+temp3,temp1+temp4);maxProfit = Math.max(maxProfit,temp2+temp3);maxProfit = Math.max(maxProfit,temp2+temp4);}// 将结果存入缓存memo[canRob].put(root, maxProfit);return maxProfit;}}

返回值是数组的实现

class Solution {public int rob(TreeNode root) {int[] result = robSub(root);return Math.max(result[0], result[1]);}//res[0] 表示不偷当前节点时的最大值。//res[1] 表示偷当前节点时的最大值。private int[] robSub(TreeNode node) {if (node == null) {return new int[2];}int[] left = robSub(node.left);int[] right = robSub(node.right);int[] res = new int[2];// 如果不偷当前节点,那么子节点可以偷也可以不偷,取决于哪种选择更优res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);// 如果偷当前节点,那么子节点就不能偷res[1] = node.val + left[0] + right[0];return res;}
}

2560. 打家劫舍 IV

沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋 。小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃取的 最大金额 。给你一个整数数组 nums 表示每间房屋存放的现金金额。形式上,从左起第 i 间房屋中放有 nums[i] 美元。另给你一个整数 k ,表示窃贼将会窃取的 最少 房屋数。小偷总能窃取至少 k 间房屋。返回小偷的 最小 窃取能力。

思路分析 

单调性如果小偷可以在某个窃取能力x下窃取至少k间房屋,那么他也能在任何大于x的能力下做到同样的事情。这是因为增加窃取能力意味着更多房屋的金额成为可选项。这种单调递增关系是二分查找可行性的关键。

参考博客

LeetCode887之鸡蛋掉落(相关话题:动态规划,二分法)_鸡蛋掉落二分法是否有效率提高的空间?包括空间效率和时间效率。-CSDN博客

class Solution {public int minCapability(int[] nums, int k) {// 初始化二分搜索的边界int lower = Arrays.stream(nums).min().getAsInt(); // 找到数组中的最小值,作为最低可能的窃取能力int upper = Arrays.stream(nums).max().getAsInt(); // 找到数组中的最大值,作为最高可能的窃取能力// 执行二分搜索while (lower <= upper) {int middle = (lower + upper) / 2; // 计算中间值作为当前的窃取能力int count = 0; // 用来计数在当前窃取能力下可以窃取的不相邻房屋数boolean visited = false; // 用于标记上一间房屋是否已被窃取// 遍历房屋数组,判断在当前窃取能力下的窃取情况for (int x : nums) {if (x <= middle && !visited) {// 如果当前房屋的金额不超过middle,并且上一间房屋没有被窃取count++; // 增加计数visited = true; // 标记当前房屋已被窃取} else {// 如果当前房屋的金额超过middle或上一间房屋已被窃取visited = false; // 重置visited,表示当前房屋没有被窃取}}// 判断是否能满足至少窃取k间房屋的条件if (count >= k) {// 如果可以窃取的房屋数量大于等于kupper = middle - 1; // 降低窃取能力的上界,尝试找到更小的窃取能力} else {// 如果不能满足窃取至少k间房屋lower = middle + 1; // 增加窃取能力的下界,尝试更高的窃取能力}}// 当lower > upper时,lower即为所求的最小窃取能力return lower;}
}

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

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

相关文章

【Qt】QWidget核心属性相关API

目录 一. enabled——是否可用 二. geometry——几何位置 window frame 三. windowTitle——窗口标题 四. windowIcon——窗口图标 ​qrc文件 五. windowOpacity——透明度 六. cursor——光标 自定义光标 七. font——字体 八. toolTip——提示栏 九. focusPolic…

【QT】QT 概述(背景介绍、搭建开发环境、Qt Creator、程序、项目文件解析、编程注意事项)

一、Qt 背景介绍 1、什么是 Qt Qt 是一个跨平台的 C 图形用户界面应用程序框架。 它为应用程序开发者提供了建立艺术级图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展。Qt 为开发者提供了一种基于组件的开发模式&#xff0c;开发者可以通过简单的拖拽和…

天空星LVGL移植记录

一、移植的LVGL版本8.2 下载地址&#xff1a;&#xff08;网页下个加速脚本&#xff09;GitHub - lvgl/lvgl: Embedded graphics library to create beautiful UIs for any MCU, MPU and display type.https://github.com/lvgl/lvgl 二、硬件设备 天空星STM32F407VET6 ILI9…

vue3中provide 和 inject 用法#Vue3中解决局部刷新问题

vue3中provide 和 inject 用法#Vue3中解决局部刷新问题 在父子组件传递数据时&#xff0c;通常使用的是 props 和 emit&#xff0c;父传子时&#xff0c;使用的是 props&#xff0c;如果是父组件传孙组件时&#xff0c;就需要先传给子组件&#xff0c;子组件再传给孙组件&…

【JavaScript 算法】KMP算法:高效的字符串匹配

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理部分匹配表的构建 二、算法实现构建部分匹配表KMP字符串匹配注释说明&#xff1a; 三、应用场景四、总结 KMP算法&#xff08;Knuth-Morris-Pratt Algorithm&#xff09;是一种用于在文本中高效查找子串的字符串…

昇思学习打卡-21-生成式/Diffusion扩散模型

文章目录 Diffusion扩散模型介绍模型推理结果 Diffusion扩散模型介绍 关于扩散模型&#xff08;Diffusion Models&#xff09;有很多种理解&#xff0c;除了本文介绍的离散时间视角外&#xff0c;还有连续时间视角、概率分布转换视角、马尔可夫链视角、能量函数视角、数据增强…

【BUG】已解决:AttributeError: ‘DataFrame‘ object has no attribute ‘append‘

已解决&#xff1a;AttributeError: ‘DataFrame‘ object has no attribute ‘append‘ 目录 已解决&#xff1a;AttributeError: ‘DataFrame‘ object has no attribute ‘append‘ 【常见模块错误】 错误原因&#xff1a; 解决办法&#xff1a; 欢迎来到英杰社区https:/…

215. 数组中的第K个最大元素 347. 前 K 个高频元素(LeetCode热题100)

215. 数组中的第K个最大元素 - 力扣&#xff08;LeetCode&#xff09; 写个快排&#xff0c;使数组升序&#xff0c;返回倒数第k个元素即可 func quickSort(nums []int, l int, r int) {if l > r {return}x : nums[(l r) / 2]i : l - 1j : r 1for i < j {for {iif n…

[力扣Java解题分享]12.74搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。…

大鲸鱼docker-compose单机容器集群编排工具

目录 一、Docker-compose 概述 二、Docker-compose简介 三、YML文件格式及编写注意事项 1.yml文件是什么 2.yml问价使用注意事项 3.yml文件的基本数据结构 四、Docker-compose 配置 1.Docker-Compose 配置常用字段 2.Docker Compose常用命令 3.使用Docker-compose创建…

【笔记:3D航路规划算法】一、随机搜索锚点(python实现,讲解思路)

目录 关键概念3D路径规划算法1. A*算法2. 快速随机锚点1. 初始化&#xff1a;2. 实例化搜索算法&#xff1a;3. 路径生成&#xff1a;4. 绘制图像&#xff1a; 3D路径规划是在三维空间中寻找从起点到终点的最短或最优路径的一种技术。它广泛应用于无人机导航、机器人运动规划、…

【医学影像】X86+FPGA:支持AI医学影像设备应用的工控主板,赋能CT、MRI、X线、超声等医学影像设备

支持AI医学影像设备应用的工控主板 在我国人口老龄化问题不断加剧&#xff0c;对影像诊断需求持续增长&#xff0c;和国家利好高端医学影像市场发展的系列法规和政策接连出台的大环境下&#xff0c;AI医学影像设备产业迎来发展黄金期。紧跟发展大势&#xff0c;基于12/13代 In…

Federated Graph Augmentation for Semisupervised Node Classification

文章目录 1 本文的主要贡献2 FedGA 模型3 FedGA-L 模型3.1 模型的思想3.2 模型具体步骤 4 实验 1 本文的主要贡献 解决图联邦学习中利用图拓扑结构和无标签节点数据的难题&#xff0c;提出了一种称为联合图增强(FedGA)的新方法&#xff0c;以更好地利用拓扑信息&#xff0c;然…

【python学习】python的知识点总结、特点和思考及解答(代码示例)

引言 python 是一种高级编程语言&#xff0c;具有简洁的语法和丰富的库&#xff0c;被广泛应用于Web开发、数据分析、人工智能、科学计算等领域 文章目录 引言一、python知识点总结1.1 基础语法1.1.1 变量和数据类型1.1.2 控制结构1.1.3 函数和模块 1.2 面向对象编程1.2.1 类和…

如何通过成熟的外发平台,实现文档安全外发管理?

文档安全外发管理是企业信息安全管理的重要组成部分&#xff0c;它涉及到企业向外发送的文件&#xff0c;需要进行严格的控制和管理&#xff0c;防止敏感或机密信息的泄露。以下是一些关键考虑因素&#xff1a; 文件外发的挑战&#xff1a;企业在文件外发时面临的主要挑战包括…

wls2下的centos使用桥接模式连接宿主机网络独立静态ip

前提&#xff1a;wsl2已安装&#xff0c;可正常更新 1.在控制面板中&#xff0c;打开开启或关闭windows功能&#xff0c;将里面的 Hyper-V功能打开&#xff0c;此处涉及重启 2. 按一下win键&#xff0c;输入hy&#xff0c;上面可以看到Hyper-V Manager,点进去 3.选择右边的 Vi…

Fiddler抓包

一个不错的文档&#xff1a;萌新要入行-CSDN博客 测试之路&#xff1a;3年经验来面试20K的测试岗&#xff0c;连基本功都不会&#xff0c;还不如去招应届生 Fiddler教程&#xff1a;https://www.cnblogs.com/zhangyangcheng/articles/15218175.html Fiddler安装教程&#xff1…

F5理念左移,实现API安全的全生命周期管理

API是我们现代数字生活中隐形的中枢神经系统&#xff0c;从远程医疗到在线银行&#xff0c;实时API让世界变得更美好。不可否认的是&#xff0c;当应用程序和架构发生变化时&#xff0c;攻击面也会随之变化。传统的安全措施&#xff0c;比如WAF、DDoS和Bot防护仍然必不可少&…

java中传引用问题

在 Java 中&#xff0c;所有对象都是通过引用传递的&#xff0c;而基本数据类型是通过值传递的。 引用传递&#xff1a; 当一个对象作为参数传递给方法时&#xff0c;传递的是对象的引用。对这个对象引用进行的修改会影响到原始对象。例如&#xff1a; public class Test {p…

在eclipse中使用Junit单元测试的准备工作和基本介绍

JUnit准备工作和基本介绍 JUnit是一个Java语言的单元测试框架。。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。 Junit 测试也是程序员测试&#xff0c;即所谓的白盒测试&#xff0c;它需要程序员知道被测试的代码如何完成功能&#xff0c;以及完成什么样的功能 …