9 动态规划

article/2025/7/5 6:57:00

9.3 爬楼梯

从1开始举例子发现规律

dp[i]=dp[i-1]+dp[i-2];
class Solution {
public:int climbStairs(int n) {if(n<=1){return 1;}vector<int>dp(n+1);dp[2]=2;dp[1]=1;for(int i=3;i<=n;i++){dp[i]=dp[i-1]+dp[i-2];}return dp[n];}
};

9.29 打家劫舍

1 确定dp数组下标与元素的含义

以当前元素结尾的能偷窃到的最多的钱

class Solution {
public:int rob(vector<int>& nums) {if(nums.size()==0) return 0;if(nums.size()==1)return nums[0];//1 dp数组含义:元素为以当前nums数组元素结尾的打家劫舍的最大值vector<int>dp(nums.size(),0);//3 初始化dp[0]=nums[0];dp[1]=max(nums[0],nums[1]);//关键点:这个也是要符合下面的公式的 //dp[i]=max(dp[i-2]+nums[i],dp[i-1]);dp[i-2]不存在,nums[i]=nums[1],dp[i-1]=dp[0]=nums[0]。//4 确定遍历方向for(int i=2;i<nums.size();i++){dp[i]=max(dp[i-2]+nums[i],dp[i-1]);//2 递归公式}return dp[nums.size()-1];}
};

9.31 打家劫舍3

该题是动态二叉树

背过就好,最大的特点就是递归函数返回值类型为动态数组,里面包含了左或右节点偷还是不偷的时候的能取到的最大值。

class Solution {
public:int rob(TreeNode* root) {vector<int>result=rob1(root);return max(result[0],result[1]);}vector<int> rob1(TreeNode* root){if(root==nullptr){return vector<int>{0,0};//0:偷,1:不}vector<int>leftRob=rob1(root->left);vector<int>rightRob=rob1(root->right);//该层递归逻辑//偷该节点,那么左右节点都不能偷int cur0=root->val+leftRob[1]+rightRob[1];//关键点:root->val把该节点的值加上去//不偷该节点int cur1=max(leftRob[0],leftRob[1])+max(rightRob[0],rightRob[1]);return vector<int>{cur0,cur1};//递归函数的return写在递归逻辑里。}};

 9.32 买卖股票的最佳时机

本题难点在分析dp递推公式和确定dp含义上

1 dp数组含义

dp[i][0] 表示第i天持有股票所得最多现金

dp[i][1] 表示第i天不持有股票所得最多现金

持有和买入不一样,今天持有也可能是昨天买入的

2 dp数组递推公式

dp[i][0]表示di天持有股票所得最多的现金,第i天持有股票有可能是今天买入的(-price[i]),也可能是昨天甚至前天、大前天、之前 的某一天买入的(dp[i-1][0]),那就不变

dp[i][1] 表示第i天不持有股票所得最多现金,第一种情况,之前持有了股票但是今天卖出了(dp[i-1][0]+price[i])第二种情况,根本没买(dip[i-1][1])

dp[i][0] = max(dp[i - 1][0], -prices[i]);
//-prices[i]的真正形式应该是dp[i-1][1]-price[i]=0-prices[i],
//由于该题股票只能买卖一次,所以当从非持有状态转移到非持有状态时,用户的利润只能是-prices[i],因为只能买卖一次,买之前用户的利润一定是0。
dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);

3 初始条件

dp[0][0]=-price[0]

dp[0][1]=0

4 确定遍历顺序

递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历

class Solution {
public:int maxProfit(vector<int>& prices) {if(prices.size()==0){return 0;}vector<vector<int>>dp(prices.size(),vector<int>(2));//0:持有,1:没持有dp[0][0]=-prices[0];dp[0][1]=0;for(int i=1;i<prices.size();i++){dp[i][0]=max(-prices[i],dp[i-1][0]);dp[i][1]=max(dp[i-1][0]+prices[i],dp[i-1][1]);}return dp[prices.size()-1][1];}
};

 9.34 买卖股票的最佳时机2 

 该题股票可以买卖多次,

所以用户的状态为持有时(0),第一种情况:一直都是持有dp[i-1][0],第二种情况:dp[i][0]可能是卖了又买的-prices[i]+dp[i-1][1]

dp[i][0] = max(dp[i - 1][0], dp[i-1][1]-prices[i]);dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);

 答案:

class Solution {
public:int maxProfit(vector<int>& prices) {int len=prices.size();vector<vector<int>>dp(len,vector<int>(2));dp[0][0]=-prices[0];dp[0][1]=0;for(int i=1;i<len;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i]);//持有状态:1 原本就持有。2 上一个节点不持有(可能是之前的某个节点卖了)又在当前这个节点买的。dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]);//非持有状态:1 原本不持有。2 上一个节点持有,在当前节点卖了}return dp[len-1][1];}
};

9.34 买卖股票的最佳时机(含冷冻期)

递推公式

//0:持有:1 上一个节点就持有,今天没买入 2 昨天不持有且非昨天卖出且今天买入 3昨天是冷冻期,今天买入 
//1:不持有(非今天卖出):1 昨天就不持有且非昨天卖出今天不买 2 昨天是冷冻期,今天也没买入
//2:不持有(今天卖出):1 昨天持有今天卖出
//3 :冷冻期:1 原本就不持有且昨天卖出,今天啥也没干
// dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i],dp[i-1][3]-prices[i]);
// dp[i][1]=max(dp[i-1][1], dp[i-1][3]);
// dp[i][2]=dp[i-1][0]+prices[i];
// dp[i][3]=dp[i-1][2];

思路

class Solution {
public:int maxProfit(vector<int>& prices) {int len =prices.size();vector<vector<int>>dp(len,vector<int>(4,0));dp[0][0]=-prices[0];//0:持有:1 上一个节点就持有,今天没买入 2 昨天不持有且非昨天卖出且今天买入 3昨天是冷冻期,今天买入 //1:不持有(非今天卖出):1 昨天就不持有且非昨天卖出今天不买 2 昨天是冷冻期,今天也没买入//2:不持有(今天卖出):1 昨天持有今天卖出//3 :冷冻期:1 原本就不持有且昨天卖出,今天啥也没干// dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i],dp[i-1][3]-prices[i]);// dp[i][1]=max(dp[i-1][1], dp[i-1][3]);// dp[i][2]=dp[i-1][0]+prices[i];// dp[i][3]=dp[i-1][2];for(int i=1;i<len;i++){dp[i][0]=max(dp[i-1][0],max(dp[i-1][1]-prices[i],dp[i-1][3]-prices[i]));dp[i][1]=max(dp[i-1][1], dp[i-1][3]);dp[i][2]=dp[i-1][0]+prices[i];dp[i][3]=dp[i-1][2];}return max(dp[len-1][1],max(dp[len-1][2],dp[len-1][3]));}
};

9.46 最大子序和

动态规划五步曲

1 确定dp[i]的元素和下标的含义

确定dp[i]的元素为以i为结尾的所有子序和的最大值

2 确定递推公式

两种情况,第一种就是当前遍历到的nums数组的元素加上dp[i-1]。第二种就是当前遍历到的nums数组的元素(为啥不是只有第一种情况呢?因为dp[i-1]有可能是负数)

3 初始化

由dp[i]的定义可知,dp[0]=nums[0];

4 确定遍历顺序

递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历

5 举例推导dp数组

9.52 回文子串

动态规划法:

递推公式思想:假设s[i]=s[j],且[i+1, j-1]内的字符串是回文串,那么[i, j]内的字符串一定是回文串。

 双指针法:

遍历整个字符串,

9.52 最长回文子序列

思路:

1 dp[i][j]数组元素的具体含义

字符串下标[i, j]里的最长回文串的长度

2 递推公式

if(s[i]==s[j]){dp[i][j]=dp[i+1][j-1]+2;
}else{dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
}

 3 初始化

for(int i=0;i<s.size();i++){dp[i][i]=1;
}

 4 确定遍历顺序

i为竖坐标,j为横坐标

由下图可知,i从后往前遍历,j正好相反

i的遍历范围为(s.size()-2, 0), j为(j+1, s.size()-1)

(对于该题,画画图,看出来遍历范围,直接写实际的遍历范围,不要全部遍历,否则极容易造成数组越界问题!!!)

class Solution {
public:int longestPalindromeSubseq(string s) {vector<vector<int>>dp(s.size(),vector<int>(s.size(),0));for(int i=0;i<s.size();i++){dp[i][i]=1;}for(int i=s.size()-1 ;i>=0;i--){for(int j=i+1;j<s.size();j++){if(s[i]==s[j]){dp[i][j]=dp[i+1][j-1]+2;}else{dp[i][j]=max(dp[i+1][j],dp[i][j-1]);}}}return dp[0][s.size()-1];}
};

2 找不到归属的

2.1 比特位数组

 

答案:

class Solution {
public:vector<int> countBits(int n) {vector<int>result;for(int i=0;i<=n;i++){result.push_back(compute(i));}return result;}int compute(int n){int i=0;while(n!=0){int m=n%2;if(m==1){i++;}n=n/2;}return i;}
};


http://www.hkcw.cn/article/dpUGjNZrmq.shtml

相关文章

Playwright 测试框架 - Node.js

🚀超全实战:基于 Playwright + Node.js 的自动化测试项目教程【附源码】 📌 本文适合自动化测试入门者 & 前端测试实战者。从零开始手把手教你搭建一个 Playwright + Node.js 项目,涵盖配置、测试用例编写、运行与调试、报告生成以及实用进阶技巧。建议收藏!👍 �…

4.RV1126-OPENCV 图像轮廓识别

一.图像识别API 1.图像识别作用 它常用于视觉任务、目标检测、图像分割等等。在 OPENCV 中通常使用 Canny 函数、findContours 函数、drawContours 函数结合在一起去做轮廓的形检测。 2.常用的API findContours 函数&#xff1a;用于寻找图片的轮廓&#xff0c;并把所有的数…

Cursor从入门到精通实战指南(五):一键生成流程图/架构图,开发者必备收藏!

解锁Cursor&#xff1a;开启高效开发新境界 结合了GPT-4、Claude 3.5等强大的大语言模型&#xff0c;能够通过自然语言交互实现代码生成、原型设计、流程优化等功能。无论是编程新手还是经验丰富的开发者&#xff0c;都能借助Cursor的智能特性&#xff0c;快速完成复杂的编码任…

postman工具使用

基本功能操作 常用断言 定义&#xff1a;postman 断言借助 JavaScript - js 语言编写代码&#xff0c;自动判断预期结果与实际结果是否一致。&#xff08; 注意断言 代码写在 Tests 的标签中&#xff09; 断言响应状态码 断言响应体是否包含某个字符串&#xff08;Response bo…

【Elasticsearch】Elasticsearch 核心技术(一):索引

Elasticsearch 核心技术&#xff08;一&#xff09;&#xff1a;索引 1.索引的定义2.索引的命名规范3.索引的增、删、改、查3.1 创建索引3.1.1 创建空索引 3.2 删除索引3.3 文档操作3.3.1 添加/更新文档&#xff08;指定ID&#xff09;3.3.2 添加文档&#xff08;自动生成ID&am…

玩客云 OEC/OECT 笔记(2) 运行RKNN程序

目录 玩客云 OEC/OECT 笔记(1) 拆机刷入Armbian固件玩客云 OEC/OECT 笔记(2) 运行RKNN程序 RKNN OEC/OEC-Turbo 使用的芯片是 RK3566/RK3568, 这个系列是内建神经网络处理器 NPU 的, 利用 RKNN 可以部署运行 AI 模型利用 NPU 硬件加速模型推理. 要使用 NPU, 首先需要在电脑使…

【音视频】FFmpeg 硬件(NVDIA)编码H264

FFmpeg 与x264的关系 ffmpeg软编码是使⽤x264开源项⽬&#xff0c;也就是说ffmpeg软编码H264最终是调⽤了x264开源项⽬&#xff0c;所以我们要先理解ffmpeg和x264的调⽤关系&#xff0c;这⾥我们主要关注x264_init。对于x264的参数都在 ffmpeg\libavcodec \libx264.c x264\co…

深度学习和神经网络 卷积神经网络CNN

1.什么是卷积神经网络 一种前馈神经网络&#xff1b;受生物学感受野的机制提出专门处理网格结构数据的深度学习模型 核心特点&#xff1a;通过卷积操作自动提取空间局部特征&#xff08;如纹理、边缘&#xff09;&#xff0c;显著降低参数量 2.CNN的三个结构特征 局部连接&a…

论文略读:LIMO: Less is More for Reasoning

202502 arxiv 在数学推理领域&#xff0c;论文提出的LIMO仅用 817 条精心设计的训练样本&#xff0c;借助简单的监督微调&#xff0c;就全面超越了使用十万量级数据训练的主流模型 最近的大模型在预训练阶段已纳入海量数学知识&#xff08;比如Llama 3 仅在数学推理上的训练数…

web架构3------(nginx的return跳转,gzip压缩,目录浏览,访问控制和location符号优先级)

一.前言 本期继续来介绍nginx的各项配置&#xff0c;看着内容很多&#xff0c;但是主要还是介绍&#xff0c;内容还是很少的。 二.return和rewrite跳转 在我们配置ssl证书之后&#xff0c;如果把https的s去掉&#xff0c;就相当于去访问80端口了&#xff0c;https默认找的是…

大楼智能化建设设计方案(Word)

第一章 智能化设计 4 1.1 项目概况 4 1.2 设计原则 4 1.3 设计依据 6 1.4 项目总体规划 7 1.5 综合布线系统 8 1.5.1 综合布线系统 8 1.5.2 楼宇分机房系统 20 1.5.3 有线电视网 27 1.6 建筑智能化系统 37 1.6.1 周界防范系统 37 1.6.2 电子巡更系统 38 1.6.3…

Spring AI 之检索增强生成(Retrieval Augmented Generation)

检索增强生成&#xff08;RAG&#xff09;是一种技术&#xff0c;有助于克服大型语言模型在处理长篇内容、事实准确性和上下文感知方面的局限性。 Spring AI 通过提供模块化架构来支持 RAG&#xff0c;该架构允许自行构建自定义的 RAG 流程&#xff0c;或者使用 Advisor API 提…

【C++/Linux】TinyWebServer前置知识之IP协议详解

目录 IPv4地址 分类 IP数据报分片 IP 协议在传输数据报时&#xff0c;将数据报分为若干分片&#xff08;小数据报&#xff09;后进行传输&#xff0c;并在目的系统中进行重组&#xff0c;这一过程称为分片&#xff08;Fragmentation&#xff09;。 IP模块工作流程​编辑 I…

破局软件开发困境:一套‘一模到底‘的功能模型,如何撬动软件工程全数字化管控?

软件工程如同一场复杂的交响乐&#xff0c;功能模型是乐谱的主旋律&#xff0c;而需求、设计、开发、测试、运维、用户反馈、Bug、版本、状态等则是丰富的配器和节奏。传统模式下&#xff0c;这些元素常常各自为营&#xff0c;声部混乱&#xff0c;难以奏出和谐的乐章。如何才能…

RAG入门 - Retriever(1)

文章目录 环境准备知识库加载1. Retriever - embeddings &#x1f5c2;️1.1 将文档拆分为chunks1.2 词嵌入1.3 构建向量数据库Nearest Neighbor search algorithm &#xff08;最近邻搜索算法&#xff09;Distances &#xff08;距离&#xff09;点积&#xff08;Dot Product&…

Pyomo中线性规划接口的使用

之前在 Pyomo介绍-CSDN博客 中以饮食为例介绍过Pyomo的使用&#xff0c;执行以下命令&#xff1a; pyomo solve --solverglpk test_pyomo_linear_programming.py ../test_data/diet.dat 直接执行以上命令&#xff0c;不便之处有以下几点&#xff1a; (1).不能直接解析python文…

打开一个新的Maven工程要做的事情

新导入项目变成maven 1、检查环境配置 2.看有没有maven 3.在idea中配置maven 4、让配置文件添加到maven项目中 变成这样基本就成功了 调出service界面 可以同时选中启动多个项目 这里可以同时关闭多个项目

GNURadio实现MIMO OFDM文件传输

文章目录 前言一、理论基础二、使用方法1、打开虚拟机2、输入密码3、运行 grc 文件4、运行 三、流图及运行结果1、MIMO_simulation.grc2、MIMO_tx.grc3、MIMO_rx.grc 四、资源自取 前言 使用 GNU Radio Companion 驱动 USRP N320 实现 MIMO OFDM 收发测试。&#xff08;Ubuntu…

达梦数据库 Windows 系统安装教程

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

【Day43】

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 今天代码见个人 Gitee仓库&#xff1a;LOVE/Python学习库https://gitee.com/love_hub/python-learning-library Github仓库&a…