打家劫舍系列 | Leetcode 198 | 213 | 337 | 动态规划 | 滚动数组

embedded/2024/10/18 16:45:40/
🙋大家好!我是毛毛张!
🌈个人首页: 神马都会亿点点的毛毛张

毛毛张今天分享的是动态规划中打家劫舍系列的题目!

文章目录

  • 题目1:[198. 打家劫舍](https://leetcode.cn/problems/house-robber/)
    • 1.题目描述
    • 2.题解
  • 题目2:[213. 打家劫舍 II](https://leetcode.cn/problems/house-robber-ii/)
    • 1.题目描述
    • 2.题解
  • 题目3:[337. 打家劫舍 III](https://leetcode.cn/problems/house-robber-iii/)
    • 1.题目描述
    • 2.题解

题目1:leetcode.cn/problems/house-robber/" rel="nofollow">198. 打家劫舍

1.题目描述

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

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

示例 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

2.题解

java">class Solution {// 定义一个公共方法rob,用来计算打劫非相邻房屋可以获得的最大金额public int rob(int[] nums) {//判断特殊情况if (nums == null || nums.length == 0) return 0;if (nums.length == 1) return nums[0];// 初始化一个动态规划数组dp,长度等于输入数组nums的长度int[] dp = new int[nums.length];// 如果只有一个房屋,那么最大金额就是这个房屋里的金额dp[0] = nums[0];// 如果有两个房屋,选择金额较大的那个房屋dp[1] = Math.max(nums[0], nums[1]);// 从第三个房屋开始遍历for (int i = 2; i < nums.length; i++) {// 对于每个房屋i,有两种选择:// 1. 不打劫房屋i,那么前一步的最大金额保持不变,即dp[i-1]// 2. 打劫房屋i,那么当前的最大金额为前两步的最大金额加上当前房屋的金额,即dp[i-2] + nums[i]// 取两种情况下的最大值作为dp[i]的值dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);}// 返回最后一个房屋的最大金额return dp[nums.length - 1];}
}

题目2:leetcode.cn/problems/house-robber-ii/" rel="nofollow">213. 打家劫舍 II

1.题目描述

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

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

示例 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

2.题解

java">// 定义一个名为 Solution 的类
class Solution {// 主方法,用于计算能够偷窃的最大金额public int rob(int[] nums) {// 如果输入数组为空或长度为0,则表示没有房子可以偷,返回0if (nums == null || nums.length == 0) return 0;// 如果只有一个房子,直接返回该房子的金额if (nums.length == 1) return nums[0];// 分别计算两种情况下的最大可偷金额:// 第一种情况:不偷最后一个房子,从第一个到最后第二个int result1 = robRange(nums, 0, nums.length - 2);// 第二种情况:不偷第一个房子,从第二个到最后一个int result2 = robRange(nums, 1, nums.length - 1);// 返回两种情况下较大的金额return Math.max(result1, result2);}// 辅助方法,用于计算从 start 到 end 范围内房间的最大可偷金额public int robRange(int[] nums, int start, int end) {// 如果开始和结束位置相同,表示只有一个房子,直接返回该房子的金额if (start == end) return nums[start];// 初始化动态规划数组,长度与输入数组相同int[] dp = new int[nums.length];// 填充初始条件dp[start] = nums[start];dp[start + 1] = Math.max(nums[start], nums[start + 1]);// 从第三个房子开始遍历for (int i = start + 2; i <= end; i++) {// 动态规划状态转移方程:当前房子的收益等于前天(i-2)的最大收益加上当前房子的价值,// 或者昨天(i-1)的最大收益(即不偷当前房子)dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);}// 返回最后一个房子位置处的最大可偷金额return dp[end];}
}

题目3:leetcode.cn/problems/house-robber-iii/" rel="nofollow">337. 打家劫舍 III

1.题目描述

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root

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

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额

示例 1:

在这里插入图片描述

输入: root = [3,2,3,null,3,null,1]
输出: 7 
解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7

示例 2:

在这里插入图片描述

输入: root = [3,4,5,1,3,null,1]
输出: 9
解释: 小偷一晚能够盗取的最高金额 4 + 5 = 9

提示:

  • 树的节点数在 [ 1 , 1 0 4 ] [1, 10^4] [1,104] 范围内
  • 0 < = N o d e . v a l < = 1 0 4 0 <= Node.val <= 10^4 0<=Node.val<=104

2.题解

2.1 递归-超时

java">class Solution {public int rob(TreeNode root) {//递归if(root == null) return 0;int money = root.val;if(root.left != null){money += rob(root.left.left) + rob(root.left.right);}if(root.right != null){money += rob(root.right.left) + rob(root.right.right);}return Math.max(money,rob(root.left)+rob(root.right));}
}

2.2 记忆化递归

java">class Solution {Map<TreeNode,Integer> map = new HashMap<>();public int rob(TreeNode root) {//递归优化if(root == null) return 0;if(root.left == null && root.right == null) return root.val;if(map.containsKey(root)) return map.get(root);//偷父节点int money1 = root.val;if(root.left != null){money1 += rob(root.left.left) + rob(root.left.right);}if(root.right != null){money1 += rob(root.right.left) + rob(root.right.right);}//不偷父节点int money2 = rob(root.left)+rob(root.right);map.put(root,Math.max(money1,money2));return Math.max(money1,money2);}
}

2.3 动态规划

java">class Solution {/*** 主方法,计算以 root 为根的二叉树能抢劫的最大金额。* @param root 树的根节点。* @return 返回能抢劫的最大金额。*/public int rob(TreeNode root) {// 计算从根节点开始的子树抢劫策略int[] result = robTree(root);// 返回偷或不偷根节点时的最大金额return Math.max(result[0], result[1]);}/*** 辅助递归方法,计算从 cur 节点开始的子树的最佳抢劫策略。* @param cur 当前节点。* @return 返回一个数组,其中 result[0] 是不偷当前节点的最大金额,result[1] 是偷当前节点的最大金额。*/public int[] robTree(TreeNode cur) {// 如果当前节点为空,直接返回不偷也不抢的情况if (cur == null) return new int[]{0, 0};// 递归计算左右子树的抢劫策略int[] left = robTree(cur.left);int[] right = robTree(cur.right);// 偷当前节点,那么它的左右子节点都不能偷int money1 = cur.val + left[0] + right[0];// 不偷当前节点,那么其左右子节点可以选择偷或不偷int money2 = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);// 返回当前节点的最优策略return new int[]{money2, money1};}
}

都看到这了,不妨一键三连再走吧!

🌈欢迎和毛毛张一起探讨和交流!
联系方式参见个人主页:
神马都会亿点点的毛毛张


http://www.ppmy.cn/embedded/127273.html

相关文章

【Rust版从头写CAD】 前言

文章目录 前言 前言 Rust是一种系统级编程语言&#xff0c;注重安全性、性能和并发性&#xff0c;适用于开发高效、安全和可靠的应用程序&#xff0c;非常适合于CAD领域开发。 然而&#xff0c;要实现一个完整的CAD&#xff08;计算机辅助设计&#xff09;软件是一个复杂且耗时…

Midjourney中文版:解锁你的创意之旅

在创意与技术的交汇点&#xff0c;Midjourney中文版正等待着每一位热爱艺术、渴望表达的灵魂。这不仅仅是一款AI绘画工具&#xff0c;更是一个激发无限灵感、让创意自由翱翔的奇妙平台。 Midjourney AI超强绘画 (原生态系统&#xff09;用户端&#xff1a;Ai Loadinghttps://w…

SpinalHDL之错误集(一)

本文作为SpinalHDL学习笔记第七十六篇&#xff0c;作为错误集使用&#xff0c;类似高中生的错题集&#xff0c;记录使用SpinalHDL过程中遇到的问题&#xff0c;小到语法错误、版本兼容问题&#xff0c;大到SpinalHDL库函数错误等等&#xff0c;持续更新。 SpinalHDL学习笔记总…

【数据结构】图的最短路径

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《C游记》《进击的C》《Linux迷航》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、最短路径的概念二、Dijkstra算法2.1 思想2.2 实现 三、Bellman-Ford算法3.1 思想3.2 实现 四、Floyd-Warsh…

rv1109/rv1126 编译错误记录

rv1109/rv1126 编译错误记录 瑞芯微针对市面上的电池类IPC产品存在抓拍速度慢、识别准确性低、待机时间短、拍摄效果差及视频流畅度不佳等痛点&#xff0c;推出 rv1109 和 rv1126 电池类智慧视觉方案&#xff0c;主要定位于人工智能&#xff08;AI&#xff09;边缘计算和智能硬…

安装openai-whisper 失败

昨晚安装python 语音识别模型经常失败&#xff1a; pip install openai-whisper 具体原因是因为国外的源使网络不稳定造成断网 查阅资料我自己的解决办法是在自己C:\Users\用户名目录下建一个pip文件夹&#xff0c;在pip文件夹下建一个pip.ini文件 在pip.ini文件中加入自己要…

leetcode68:文本左右对齐

给定一个单词数组 words 和一个长度 maxWidth &#xff0c;重新排版单词&#xff0c;使其成为每行恰好有 maxWidth 个字符&#xff0c;且左右两端对齐的文本。 你应该使用 “贪心算法” 来放置给定的单词&#xff1b;也就是说&#xff0c;尽可能多地往每行中放置单词。必要时可…