Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV买卖股票的最佳时机III

Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV&&买卖股票的最佳时机III&&309.买卖股票的最佳时机含冷冻期

动态规划应该如何学习?-CSDN博客

本次题解参考自灵神的做法,大家也多多支持灵神的题解

买卖股票的最佳时机【基础算法精讲 21】_哔哩哔哩_bilibili

希望读者在阅读之前先看完这篇博客

Day43 | 动态规划 :状态机DP 买卖股票的最佳时机&&买卖股票的最佳时机II-CSDN博客

动态规划学习:

1.思考回溯法(深度优先遍历)怎么写

注意要画树形结构图

2.转成记忆化搜索

看哪些地方是重复计算的,怎么用记忆化搜索给顶替掉这些重复计算

3.把记忆化搜索翻译成动态规划

基本就是1:1转换

文章目录

  • Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV&&买卖股票的最佳时机III&&309.买卖股票的最佳时机含冷冻期
    • 188.买卖股票的最佳时机IV
      • 思路分析(子问题):
      • 1.回溯 DFS
      • 2.记忆化搜索
      • 3.1:1翻译为动态规划
      • 4.滚动数组优化
    • 123.买卖股票的最佳时机III

188.买卖股票的最佳时机IV

188. 买卖股票的最佳时机 IV - 力扣(LeetCode)

思路分析(子问题):

状态机的变化:多了一个参数j表示我们最多可以交易几笔

image-20241113171715687

在加减prices[i]的时候进行j-1,表示我们进行了一笔交易,那剩下在递归的时候最多只能交易j-1次

注意:j-1只在加prices[i]或者减prices[i]的时候写一次,加表示我们卖出,可以看做一次交易,减表示一次买进,也可以看做一次交易,但是加减prices[i]的时候都写,就说明我们买进一次再卖出算成了两次交易,这样就错了

image-20241113172010082

笔者觉得在卖出的时候进行交易次数的计算比较好,就使用这个

递归边界部分,和前两道题不同的就是j如果小于0了那肯定就是不合法的状态,因为我们的交易次数最少应该是0,所以就返回一个负无穷表示这是不合法的

1.回溯 DFS

1.返回值和参数

i是每天的价格

status是状态,表示是否持有股票

j是我们现在最多可以交易多少笔

dfs返回值是我们在前i天持有或者不持有股票,在最多交易j次的前提下可以获得的最大利润

int dfs(int i,int j,int status,vector<int>& prices)

2.终止条件

就是在前两题的基础上了一个不合法的状态,那就是交易次数小于0的话要返回负无穷

注意判断的顺序,交易次数j一定要先判断,因为只要j小于0那肯定是不合法的

		if(j<0)return INT_MIN;if(i<0)if(status==1) return INT_MIN;elsereturn 0;

3.本层逻辑

在我们加prices[i]的时候,就说明是卖出股票,就说明第i天进行了一次交易,第i天的利润是prices[i],那前i-1天的利润就是在最多交易j-1笔的情况下的最大利润,传入j-1

		if(status==1)return max(dfs(i-1,j,1,prices),dfs(i-1,j,0,prices)-prices[i]);elsereturn max(dfs(i-1,j,0,prices),dfs(i-1,j-1,1,prices)+prices[i]);

完整代码:

当然,这是超时的

class Solution {
public:int dfs(int i,int j,int status,vector<int>& prices){if(j<0)return INT_MIN;if(i<0)if(status==1) return INT_MIN;elsereturn 0;if(status==1)return max(dfs(i-1,j,1,prices),dfs(i-1,j,0,prices)-prices[i]);elsereturn max(dfs(i-1,j,0,prices),dfs(i-1,j-1,1,prices)+prices[i]);}int maxProfit(int k,vector<int>& prices) {return dfs(prices.size()-1,k,0,prices);}
}; 

2.记忆化搜索

就是搞一个哈希表dp,全都初始化为-1,每次返回前给哈希表dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了

class Solution {
public:int dfs(int i,int j,int status,vector<int>& prices,vector<vector<vector<int>>>& dp){if(j<0)return INT_MIN;if(i<0)if(status==1) return INT_MIN;elsereturn 0;if(dp[i][j][status]!=-1)return dp[i][j][status];if(status==1)return dp[i][j][status]=max(dfs(i-1,j,1,prices,dp),dfs(i-1,j,0,prices,dp)-prices[i]);elsereturn dp[i][j][status]=max(dfs(i-1,j,0,prices,dp),dfs(i-1,j-1,1,prices,dp)+prices[i]);}int maxProfit(int k,vector<int>& prices) {vector<vector<vector<int>>> dp(prices.size(),vector<vector<int>>(k+1,vector<int>(2,-1)));return dfs(prices.size()-1,k,0,prices,dp);}
}; 
//lambda
class Solution {
public:int maxProfit(int k,vector<int>& prices) {vector<vector<vector<int>>> dp(prices.size(),vector<vector<int>>(k+1,vector<int>(2,-1)));function<int(int,int,int)> dfs=[&](int i,int j,int status)->int{if(j<0)return INT_MIN;if(i<0)if(status==1) return INT_MIN;elsereturn 0;if(dp[i][j][status]!=-1)return dp[i][j][status];if(status==1)return dp[i][j][status]=max(dfs(i-1,j,1),dfs(i-1,j,0)-prices[i]);elsereturn dp[i][j][status]=max(dfs(i-1,j,0),dfs(i-1,j-1,1)+prices[i]);};return dfs(prices.size()-1,k,0);}
}; 

3.1:1翻译为动态规划

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

image-20241113173659276

dfs换成dp就是数组以及下标含义

2.确定递推公式

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

3.dp数组如何初始化(难理解的点)

1.第一维度prices.size()+1是我们的数组下标表示天数的i从1开始

2.表示交易次数的j初始化是k+2的大小是因为

-1,0,1,2,…,k一共是k+2个状态,这一点和递归里面的对应

3.对应递归的终止条件,j必须大于0才是合法的,其他的都是不合法的,所以一开始初始化都是负无穷(除以2是为了防止溢出)

然后单独把j大于0,并且是第0天(对应i<0的if),也不持有股票(对应的是递归里的if(status==0))都赋值为0,表示这种情况下没有利润

vector<vector<vector<int>>> dp(prices.size()+1,vector<vector<int>>(k+2,vector<int>(2,INT_MIN/2)));
for(int i=1;i<=k+1;i++)dp[0][i][0]=0;

4.确定遍历顺序

后续结果需要依赖前面的计算结果,故使用从前往后遍历

		for(int i=0;i<prices.size();i++){for(int j=1;j<=k+1;j++){dp[i+1][j][0]=max(dp[i][j][0],dp[i][j-1][1]+prices[i]);dp[i+1][j][1]=max(dp[i][j][1],dp[i][j][0]-prices[i]);}}

完整代码

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

4.滚动数组优化

和01背包一样,前面都是i后面都是i-1

由于j要靠j-1推出来,所以需要从后往前遍历j

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

123.买卖股票的最佳时机III

[123. 买卖股票的最佳时机 III - 力扣(LeetCode)](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/)

就是上一题k=2的情况,带进去就完了,直接结束

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

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

相关文章

FlinkSql读取kafka数据流的方法(scala)

我的scala版本为2.12 <scala.binary.version>2.12</scala.binary.version> 我的Flink版本为1.13.6 <flink.version>1.13.6</flink.version> FlinkSql读取kafka数据流需要如下依赖&#xff1a; <dependency><groupId>org.apache.flink&…

RabbitMQ实战启程:从原理到部署的全方位探索(上)

文章目录 一、RabbitMQ简介1.1、概述1.2、特性 二、RabbitMQ原理架构三、RabbitMQ应用场景3.1 简单模式3.2 工作模式3.3 发布订阅3.4 路由模式3.5 主题订阅模式 四、同类中间件对比五、RabbitMQ部署5.1 单机部署5.1.1 安装erlang5.1.2 安装rabbitmq 5.2 集群部署&#xff08;镜…

动态内存管理(c语言)

我们通常开辟空间的方式 int val 20; //大小为4个字节 char arr[10] {0} //开辟出一块连续的空间且大小为10 但是上面开辟空间方式的特点 1.空间开辟大小是固定的 2.数组在声明得时候&#xff0c;必须指定数组得长度&#xff0c;它所需要得内存在编译时分配 但是以上的方式不能…

【从零开始的LeetCode-算法】3270. 求出数字答案

给你三个 正 整数 num1 &#xff0c;num2 和 num3 。 数字 num1 &#xff0c;num2 和 num3 的数字答案 key 是一个四位数&#xff0c;定义如下&#xff1a; 一开始&#xff0c;如果有数字 少于 四位数&#xff0c;给它补 前导 0 。答案 key 的第 i 个数位&#xff08;1 < …

STM32+AI语音识别智能家居系统

基于 STM32 和 AI 语音识别的智能家居系统的详细硬件和软件设计&#xff0c;包括各个模块的详细描述和代码示例。 一、硬件设计 1. 微控制器&#xff08;STM32&#xff09;&#xff1a; 选择 STM32F7 系列或更高性能的芯片&#xff0c;如 STM32F767ZIT6&#xff0c;以满足处理…

信息收集—JS框架识别泄露提取API接口泄露FUZZ爬虫插件项目

前言 免杀结束了&#xff0c;我们开个新的篇章——信息收集。为什么我一开始先写信息收集的文章呢&#xff0c;是因为现在我才发现我的信息收集能力其实有点弱的&#xff0c;所以呢开始知不足&#xff0c;而后进。 什么是JS JS就是JavaScript的简称&#xff0c;它和Java是没…

智能化护士排班系统的设计与实现(文末附源码)

自动排班-护士(分白班|夜班) 当服务器启动时检测需要自动排班,自动开始排班的算法执行 获得本周的所有日期,例如2023-01-29.....2023-02-04依次对每个科室&#xff0c;从第一天开始,逐天进行排班&#xff0c;分别设置两个二个数组&#xff0c;day[7];night[7]分别记忆一周内每…

【原创】java+ssm+mysql社区疫情防控管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

Flink Source 详解

Flink Source 详解 原文 flip-27 FLIP-27 介绍了新版本Source 接口定义及架构 相比于SourceFunction&#xff0c;新版本的Source更具灵活性&#xff0c;原因是将“splits数据获取”与真“正数据获取”逻辑进行了分离 重要部件 Source 作为工厂类&#xff0c;会创建以下两…

CSS回顾-基础知识详解

一、引言 在前端开发领域&#xff0c;CSS 曾是构建网页视觉效果的关键&#xff0c;与 HTML、JavaScript 一起打造精彩的网络世界。但随着组件库的大量涌现&#xff0c;我们亲手书写 CSS 样式的情况越来越少&#xff0c;CSS 基础知识也逐渐被我们遗忘。 现在&#xff0c;这种遗…

11.08-10.14谷粒商城

谷粒商城--品牌管理 前端表单校验 品牌新增 品牌修改 校验规则 dataRule: {name: [{ required: true, message: "品牌名不能为空", trigger: "blur" }],logo: [{ required: true, message: "品牌logo地址不能为空", trigger: "blur"…

无插件H5播放器EasyPlayer.js网页web无插件播放器选择全屏时,视频区域并没有全屏问题的解决方案

EasyPlayer.js H5播放器&#xff0c;是一款能够同时支持HTTP、HTTP-FLV、HLS&#xff08;m3u8&#xff09;、WS、WEBRTC、FMP4视频直播与视频点播等多种协议&#xff0c;支持H.264、H.265、AAC、G711A、MP3等多种音视频编码格式&#xff0c;支持MSE、WASM、WebCodec等多种解码方…

基于Spring Boot的电子商务系统设计

5 系统实现 系统实现部分就是将系统分析&#xff0c;系统设计部分的内容通过编码进行功能实现&#xff0c;以一个实际应用系统的形式展示系统分析与系统设计的结果。前面提到的系统分析&#xff0c;系统设计最主要还是进行功能&#xff0c;系统操作逻辑的设计&#xff0c;也包括…

CSP-X2024山东小学组T2:消灭怪兽

题目链接 题目名称 题目描述 怪兽入侵了地球&#xff01; 为了抵抗入侵&#xff0c;人类设计出了按顺序排列好的 n n n 件武器&#xff0c;其中第 i i i 件武器的攻击力为 a i a_i ai​&#xff0c;可以造成 a i a_i ai​ 的伤害。 武器已经排列好了&#xff0c;因此不…

游戏引擎学习第九天

视频参考:https://www.bilibili.com/video/BV1ouUPYAErK/ 修改之前的方波数据&#xff0c;改播放正弦波 下面主要讲关于浮点数 1. char&#xff08;字符类型&#xff09; 大小&#xff1a;1 字节&#xff08;8 位&#xff09;表示方式&#xff1a;char 存储的是一个字符的 A…

JWTUtil工具类

写一个Jwt工具类 导入如下pom.xml依赖 <!--fastjson依赖--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.33</version></dependency><!--jwt依赖--><dependenc…

使用React和Vite构建一个AirBnb Experiences克隆网站

这一篇文章中&#xff0c;我会教你如何做一个AirBnb Experiences的克隆网站。主要涵盖React中Props的使用。 克隆网站最终呈现的效果&#xff1a; 1. 使用vite构建基础框架 npm create vitelatestcd airbnb-project npm install npm run dev2. 构建网站的3个部分 网站从上…

K8S containerd拉取harbor镜像

前言 接前面的环境 K8S 1.24以后开始启用docker作为CRI&#xff0c;这里用containerd拉取 参考文档 正文 vim /etc/containerd/config.toml #修改内容如下 #sandbox_image "registry.aliyuncs.com/google_containers/pause:3.10" systemd_cgroup true [plugins.…

unity小:shaderGraph不规则涟漪、波纹效果

实现概述 在本项目中&#xff0c;我们通过结合 Sine、Polar Coordinates 和 Time 节点&#xff0c;实现了动态波纹效果。以下是实现细节&#xff1a; 核心实现 Sine 波形生成&#xff1a; 使用 Sine 节点生成基本的波形。该节点能够创建周期性变化&#xff0c;为波纹效果提供…

设计模式(四)装饰器模式与命令模式

一、装饰器模式 1、意图 动态增加功能&#xff0c;相比于继承更加灵活 2、类图 Component(VisualComponent)&#xff1a;定义一个对象接口&#xff0c;可以给这些对象动态地添加职责。ConcreteComponent(TextView)&#xff1a;定义一个对象&#xff0c;可以给这个对象添加一…