算法学习day48

news/2025/3/15 7:08:26/

算法学习day48

  • 1.力扣 198.打家劫舍
    • 1.1 分析
    • 1.2 代码
  • 2.力扣213.打家劫舍II
    • 2.1 分析
    • 2.2 代码
  • 3.力扣337.打家劫舍III
    • 3.1 分析
    • 3.2 代码
  • 4.参考资料

1.力扣 198.打家劫舍

1.1 分析

1.确定dp数组以及下标的含义

dp[i] : 考虑下标i(包括i)以内的房屋,最多可以偷窃的金额数为dp[i]

2.确定递推公式

如果偷第i房间,dp[i] = dp[ i -2 ] + nums[i]。i - 1 房间不偷,下标i -2 (包括i - 2)以内的房间最多可以偷的金额为dp[i -2]加上第i房间偷的钱。

如果不偷第i房间,此时dp[i] = dp[ i -1]。

递推公式: dp[i] = max(dp[ i - 2]+ nums[i], dp[i - 1]);

3.dp数组如何初始化

由递推公式: dp[i] = max(dp[ i - 2]+ nums[i], dp[i - 1]); 递推公式的基础是dp[0]、dp[1]。

由dp的含义可知dp[0] = nums[0], dp[1] = max(nums[0] + nums[1])

初始化如下:

vector<int> dp(nums.size());
dp[0] = nums[0];
dp[1] = max(nums[0],nums[1]);

4.确定遍历顺序

dp[i] 是由dp[i-1]和dp[i-2]推导出来的,那么一定是从前到后遍历。

for(int i = 2; i < nums.size() ; i++){dp[i] = max(dp[i-2] + nums[i], dp[i -1]);
}

5.举例推导dp数组
在这里插入图片描述

1.2 代码

class Solution {
public:int rob(vector<int>& nums) {                if(nums.size() == 0) return 0;                      // 当数组为空时,直接返回 0if(nums.size() == 1) return nums[0];       // 当数组只有一个元素时,直接返回该元素的值vector<int> dp(nums.size());                     // 定义 dp 数组,长度为 nums 数组的长度dp[0] = nums[0];                                             // 初始化 dp[0] 为 nums[0]dp[1] = max(nums[0], nums[1]);             // 初始化 dp[1],选择 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];                        // 返回 dp 数组最后一个元素的值,即为所求}
};

2.力扣213.打家劫舍II

2.1 分析

1.考虑不包含首尾元素
在这里插入图片描述
2.考虑包含首元素,不包含尾元素
在这里插入图片描述
3.考虑包含尾元素,不包含首元素
在这里插入图片描述

2.2 代码

class Solution {
public:int rob(vector<int>& nums) {// 如果数组为空,直接返回0if(nums.size() == 0) return 0;// 如果数组长度为1,直接返回该数值if(nums.size() == 1) return nums[0];// 情况二:偷取[0, n-2]范围内的房屋int result1 = robRange(nums,0,nums.size() - 2);// 情况三:偷取[1, n-1]范围内的房屋int result2 = robRange(nums,1,nums.size() - 1);// 取两种情况的最大值return max(result1,result2);}// 198题:打家劫舍问题int robRange(vector<int>& nums, int start, int end){// 如果范围内只有一个房屋,直接返回该数值if(end == start) return nums[start];// 初始化dp数组,dp[i]表示偷取[0,i]范围内的房屋所能获得的最大收益vector<int> dp(nums.size());dp[start] = nums[start];// 计算dp[1]dp[start+1] = max(nums[start],nums[start+1]);// 遍历数组,计算dp[i]for(int i = start+2; i<=end; i++){// 当偷取第i个房屋时,偷取范围只能是[0, i-2],因此dp[i] = dp[i-2] + nums[i]// 当不偷取第i个房屋时,偷取范围是[0, i-1],因此dp[i] = dp[i-1]dp[i] = max(dp[i-2] + nums[i], dp[i-1]);}// 返回偷取[start, end]范围内的房屋所能获得的最大收益return dp[end];}
};

3.力扣337.打家劫舍III

3.1 分析

1.确定递归函数的参数和返回值

一个节点,偷or不偷。返回值为长度为2的数组

vector<int> robTree(TreeNode* cur){}

dp数组以及下标的含义:下标0表示不偷该节点获得的最大钱数,1表示偷该节点获得的最大钱数。

本题的dp数组是一个长度为2的数组。

2.确定终止条件

遍历过程中遇到空节点,返回。

if(cur == NULL) return vector<int>(0, 0);

3.确定遍历顺序

后序遍历。

// 下标0:不偷        下标1:偷
vector<int> left = robTree(cur->left);// 左
vector<int>right = robTree(cur->right);// 右
// 中

4.确定单层递归的逻辑

当前节点偷,由题意。左右孩子不能偷。val1= cur->val + left[0] + right[0];

如果不偷当前节点,左右孩子可偷。val2 = max(left[0],left[1]) + max(right[0],right[1]);

最后当前节点状态{val2,val1};{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}

vector<int> left = robTree(cur ->left); // 左
vector<int>right = robTree(cur->right);// 右
// 偷cur
int val1 = cur->val + left[0] + right[0];
// 不偷cur
int val2 = max(left[0], left[1]) + max(right[0], right[1]);
return {val2,val1};

5.举例推导dp数组
在这里插入图片描述

3.2 代码

class Solution {
public:int rob(TreeNode* root) {vector<int> result = robTree(root);  // 获取最终结果return max(result[0], result[1]);    // 返回最大值}// 辅助函数,返回一个长度为2的数组,表示在当前节点为根节点时偷或不偷的最大值vector<int> robTree(TreeNode* cur) {if (cur == NULL) return vector<int>{0, 0};  // 空节点返回0vector<int> left = robTree(cur->left);      // 递归处理左子树vector<int> right = robTree(cur->right);    // 递归处理右子树int val1 = cur->val + left[0] + right[0];   // 偷当前节点,左右子树都不能偷int val2 = max(left[0], left[1]) + max(right[0], right[1]); // 不偷当前节点,左右子树可偷可不偷return {val2, val1};  // 返回结果}
};

4.参考资料

[代码随想录]


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

相关文章

Java线程安全与等待通知

目录1. 线程不安全原因1.1 引入——线程不安全的例子&#xff08;抢占式执行&#xff09;1.2 线程不安全的原因&#xff08;5点其他&#xff09;2. 抢占式执行引起的线程不安全——synchronized3. 内存可见性引起的线程不安全——volatile3.1 例子——编译器优化误判3.2 volati…

点云学习(1): 获取点云的包络框

1. 记录一些容易忘记的点云操作----后续一定补充 1.获取点云的包络框 下面的get_axis_aligned_bounding_box(),get_min_bound(),get_max_bound()等函数非常好用 import open3d as o3d import numpy as np# 读取点云数据 pcd o3d.io.read_point_cloud("input.pcd"…

SQL 子查询和链接查询

1.题目&#xff1a;现在运营想要查看所有来自浙江大学的用户题目回答明细情况&#xff0c;请你取出相应数据 question_practice_detail 答题详情表 user_profile 用户表 期望结果&#xff1a; 链表查询&#xff1a; 将question_practice_detail作为基础表&#xff0c;进行u…

【云原生】Swarm解决docker server的集群化管理和部署

一文理解Swarm解决docker server的集群化管理和部署一、简介1.1、涉及到哪些概念&#xff1f;1.2、需要注意什么&#xff1f;二、集群管理2.1、创建集群2.2、将节点加入集群2.3、查看集群状态。2.4、将节点从集群中移除2.5、更新集群2.6、锁定/解锁集群三、节点管理四、服务部署…

JSON 与 Ajax

JSON 与 Ajax AJAX 就是异步 JavaScript 和 XML&#xff0c;它是一组用于客户端的相互关联的 Web 开发技术&#xff0c;以创建异步 Web 应用程序。遵循 AJAX 模型&#xff0c;Web 应用程序可以以异步的方式发送数据以及从服务器上检索数据&#xff0c;而不影响现有页面的显示行…

044:cesium加载单个图片形成底图

第044个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载单个图片形成底图. 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共78行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://x…

【MATLAB】一篇文章带你了解beatxbx工具箱使用

目录 一篇文章带你了解beatxbx工具箱使用 一篇文章带你了解beatxbx工具箱使用 clc;clear; tic; % step1 初始化 % 个体数量 NIND = 35; % 最大遗传代数 MAXGEN = 180; % 变量的维数 NVAR = 2; % 变量的二进制位数 % 上下界 bounds=[-10 10-10 10]; precision=0.0001; %运算精度…

67页新型智慧城市整体规划建设方案

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用&#xff0c;如有侵权请联系删除 新型智慧城市总体规划智慧城市基础平台的定位对于省&#xff1a;智慧城市建设是省数字政府的核心节点和重要一环 对于市直单位&#xff1a;智慧城市基础平台是全市数据资源和公…