代码随想录算法训练营第48天 |198、213、337

news/2025/1/18 7:31:50/

198. 打家劫舍

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例1:
输入: [ 1 , 2 , 3 , 1 ] [1,2,3,1] [1,2,3,1]
输出: 4 4 4
示例2:
输入: [ 2 , 7 , 9 , 3 , 1 ] [2,7,9,3,1] [2,7,9,3,1]
输出: 12 12 12

思路

本题看题能看出基本的动态规划思路,即,是偷本房屋的还是偷上一个房屋的。
dp[i] = max(dp[i-2]+nums[i],dp[i-1])

解法

class Solution {public int rob(int[] nums) {if(nums == null || nums.length == 0){return 0;}if(nums.length == 1){return nums[0];}int[] dp = new int[nums.length];dp[0] = nums[0];dp[1] = Math.max(dp[0],nums[1]);for(int i = 2;i<nums.length;i++){dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);}return dp[nums.length-1];}
}

总结

打家劫舍是动态规划的一个经典应用,重在能够加深对于动态规划数组的理解。

213. 打家劫舍Ⅱ

题目描述

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

思路

本题是打家劫舍的2.0版本,主要的改动在于,把之前排成一排的房子变成了环形,那么其实本质上的动态规划策略是不变的,只是因为房屋排列方式的变化而需要我们增加一些限制的条件。
而这里需要考虑的就是首尾元素要不要取,取谁。根据此可以分为不取首和不取尾两种情况。

解法

class Solution {public int rob(int[] nums) {if(nums == null || nums.length == 0){return 0;}int len = nums.length;if(len == 1){return nums[0];}return Math.max(helper(nums,0,len-1),helper(nums,1,len));}public int helper(int[] nums,int start,int end){int x = 0,y = 0,z = 0;for(int i = start;i<end;i++){y = z;z = Math.max(y,x+nums[i]);x = y;}return z;}
}

总结

是打家劫舍的升级版,也是对其的另一种应用。重点在于能够看出环结构房屋的限制需要体现在动态规划之外的限制中。

337. 打家劫舍Ⅲ

题目描述

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
示例1:
输入: r o o t = [ 3 , 2 , 3 , n u l l , 3 , n u l l , 1 ] root = [3,2,3,null,3,null,1] root=[3,2,3,null,3,null,1]
输出: 7 7 7
示例2:
输入: r o o t = [ 3 , 4 , 5 , 1 , 3 , n u l l , 1 ] root = [3,4,5,1,3,null,1] root=[3,4,5,1,3,null,1]
输出: 9 9 9

思路

我真的觉得,第一次见这种树上动态规划时,它是值得困难标签的。懵掉,直接上答案吧。
本题的难点主要在于,要将树遍历的递归和动态规划相结合,这个怎么结合就很有说法。
1、确定递归函数:
dp数组及其下标的含义在于:下标为0记录不偷该节点所得到的最大金钱,下标为1记录偷该节点所得到的最大金钱,故而dp数组为一个长度为2的数组。
这里需要提出的也是我之前的一个困惑点,就是长度为2的数组其实是无法标记树中每个节点的状态的。这里其实是因为,确实不用,递归过程中系统栈实惠保存每一层的递归参数的,或者说,递归过程中,想得到参数是可以调用的。
2、确定终止条件
遇到空节点,返回
3、确定遍历顺序
树的后序遍历,因为需要通过递归函数的返回值来做下一步的计算
递归左孩子得到左孩子偷与不偷的金钱
递归右孩子得到右孩子偷与不偷的金钱
4、确定单层递归的逻辑
如果偷当前节点,那么左右孩子就不能偷。
如果不偷当前节点,那么左右孩子就可以偷。
最后计算最大金钱。

解法

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public int rob(TreeNode root) {int[] res = robAction(root);return Math.max(res[0],res[1]);}public int[] robAction(TreeNode root){int[] res = new int[2];if(root == null){return res;}int[] left = robAction(root.left);int[] right = robAction(root.right);res[0] = Math.max(left[0],left[1])+Math.max(right[0],right[1]);res[1] = root.val+left[0]+right[0];return res;}
}

总结

本题其实也可以纯粹后序遍历,也能做,但是超时了。
还可以通过遍历过程中记录中间结果,但都没有动态规划简单,或者说是,代码上的简单。
答案中提到本题算是树形动态规划的入门题,这守门员属实是不简单啊。


http://www.ppmy.cn/news/73741.html

相关文章

车规级MCU芯片

作为车辆控制的核心器件&#xff0c;MCU主要用于车身控制、驾驶控制、信息娱乐和驾驶辅助系统。 8位MCU &#xff1a;提供低端控制功能:风扇控制、空调控制、雨刷、天窗、 车窗升降、低端仪表盘、集线盒、座椅控制、门控模块。 16位MCU &#xff1a;提供中端控制功能:用于动力…

STM32G4xx USB CDC 基础教程

目录 USB CDC 简介 准备工作 USB CDC配置 代码实现 数据发送 数据接收 数据传输测试 总结 大家好&#xff0c;今天我们来讨论一下如何在STM32G4xx系列微控制器中实现USB CDC(Communication Device Class)通信。USB CDC协议通常用于模拟串口通信&#xff0c;它使我们能够…

读书|林曦:她把自己的生活,过成了无用但丰盈的美学

时代在以加速度的方式变化&#xff0c;让人难以从容。而当我们陷于横向的比较系统&#xff0c;权衡着卷、躺、润时&#xff0c;也有人在探寻另一条纵向的路——向古人学习&#xff0c;以传统美学关照和滋养当下生活。      立夏之际&#xff0c;水墨画家林曦的新作《无用之…

c++ 11标准模板(STL) std::set(十)

定义于头文件 <set> template< class Key, class Compare std::less<Key>, class Allocator std::allocator<Key> > class set;(1)namespace pmr { template <class Key, class Compare std::less<Key>> using se…

【Java EE】Springboot

Springboot Springboot 核心功能SpringBoot的相关好处 Springboot 核心功能 1、 可独立运行的Spring项目&#xff1a;Spring Boot可以以jar包的形式独立运行。 2、 内嵌的Servlet容器&#xff1a;Spring Boot可以选择内嵌Tomcat、Jetty或者Undertow&#xff0c;无须以war包形…

系统学习大模型的20篇论文

【引子】“脚踏实地&#xff0c;仰望星空”&#xff0c; 知其然还要知其所以然。读论文是一条重要的途径&#xff0c;这一篇文章https://magazine.sebastianraschka.com/p/understanding-large-language-models非常值得借鉴&#xff0c;不敢私藏&#xff0c;编译成文。 大型语言…

Java操作MongoDB

上一篇文章: http://blog.csdn.net/gaowenhui2008/article/details/40045719 介绍到了在MongoDB的控制台完成MongoDB的数据操作&#xff0c;通过前一篇文章我们对MongoDB有了全面的认识和理解。现在我们就用Java来操作MongoDB的数据。 开发环境&#xff1a; System&#xff1a…

深度学习图像识别模型:递归神经网络

深度学习是一种人工智能技术&#xff0c;它用于解决各种问题&#xff0c;包括自然语言处理、计算机视觉等。递归神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是深度学习中的一种神经网络模型&#xff0c;主要用于处理序列数据&#xff0c;例如文本…