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

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
      • 思路:
      • 1.回溯法
      • 2.记忆化搜索
      • 3.动态规划

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的情况,带进去就完了,直接结束

##309.买卖股票的最佳时机含冷冻期

309. 买卖股票的最佳时机含冷冻期 - 力扣(LeetCode)

这题笔者还不够理解,后续再刷的时候再次回顾

思路:

在 122. 买卖股票的最佳时机 II 的基础上,只需修改一处:在计算持有股票的状态时,把 dfs(i−1,0) 改成 dfs(i−2,0)。道理和 198. 打家劫舍 是一样的,因为第 i 天买股票的话第 i−1 天不能卖,只能从第 i−2 天没有股票的状态转移过来。注意 dfs(i−2,0) 并不意味着第 i−2 天一定卖了股票,而是在没有股票下的最优状态。

请注意,这会导致边界条件多了一个 dfs(−2,0)=0

请注意,dfs(−2,1) 是访问不到的,所以下面翻译成递推时,无需初始化这个状态(不需要写 f[0][1]=−∞)。

1.回溯法

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

2.记忆化搜索

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

3.动态规划

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

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Koa进阶:掌握中间件和参数校验的艺术

目录 一、首先下载依赖 二、在index.js中引入koa-parameter&#xff0c;一般挂载这个中间件时会放在注册请求体的后面 三、使用实例 四、如果跟我们所需求的参数不同&#xff0c;返回结果直接会返回422 koa-parameter一般是用来校验请求传过来的参数是否是自己所需要的的 G…

opencv(c++)----图像的读取以及显示

opencv(c)----图像的读取以及显示 imread: 作用&#xff1a;读取图像文件并将其加载到 Mat 对象中。参数&#xff1a; 第一个参数是文件路径&#xff0c;可以是相对路径或绝对路径。第二个参数是读取标志&#xff0c;比如 IMREAD_COLOR 表示以彩色模式读取图像。 返回值&#x…

git config是做什么的?

git config是做什么的&#xff1f; git config作用配置级别三种配置级别的介绍及使用&#xff0c;配置文件说明 使用说明git confi查看参数 默认/不使用这个参数 情况下 Git 使用哪个配置等级&#xff1f; 一些常见的行为查看配置信息设置配置信息删除配置信息 一些常用的配置信…

【计算机网络】【传输层】【习题】

计算机网络-传输层-习题 文章目录 10. 图 5-29 给出了 TCP 连接建立的三次握手与连接释放的四次握手过程。根据 TCP 协议的工作原理&#xff0c;请填写图 5-29 中 ①~⑧ 位置的序号值。答案技巧 注&#xff1a;本文基于《计算机网络》&#xff08;第5版&#xff09;吴功宜、吴英…

【二叉搜素树】——LeetCode二叉树问题集锦:6个实用题目和解题思路

文章目录 计算布尔二叉树的值求根节点到叶节点的数字之和二叉树剪枝验证二叉搜索树二叉搜索树中第K小的元素二叉树的所有路径 计算布尔二叉树的值 解题思路&#xff1a; 这是一个二叉树的布尔评估问题。树的每个节点包含一个值&#xff0c;其中叶子节点值为 0 或 1&#xff0…

2023年MathorCup数学建模A题量子计算机在信用评分卡组合优化中的应用解题全过程文档加程序

2023年第十三届MathorCup高校数学建模挑战赛 A题 量子计算机在信用评分卡组合优化中的应用 原题再现&#xff1a; 在银行信用卡或相关的贷款等业务中&#xff0c;对客户授信之前&#xff0c;需要先通过各种审核规则对客户的信用等级进行评定&#xff0c;通过评定后的客户才能…

嵌入式开发套件(golang版本)

1. watchdog&#xff08;软件看门狗&#xff1a;守护升级&#xff09; 2. gate&#xff08;主程序&#xff09; 3. web&#xff08;api版本 升级包&#xff09; OTA 升级流程 watchdog启动后检查守护进程gate是否正在运行&#xff0c;如果没有&#xff0c;api对比版本号&am…

解压专家 2.4.12| 多功能解压缩工具,支持密码共享、音乐播放和歌词匹配。

解压专家是一款功能强大的解压缩软件&#xff0c;提供了类似于WIFI万能钥匙的密码分享功能&#xff0c;帮助用户快速获取共享的解压密码。作为专业的解压缩工具&#xff0c;它支持多种常见和不常见的压缩包格式&#xff0c;如ZIP、RAR、7z、TAR.GZ和ISO等&#xff0c;并且还支持…

并发编程(10)——内存模型和原子操作

文章目录 十、day101. 内存模型基础1.1 对象和内存区域1.2 改动序列 2. 原子操作及其类型2.1 原子操作2.2 原子类型2.3 内存次序2.4 std::atomic_flag2.4.1 自旋锁 2.5 std::atomic&#xff1c;bool&#xff1e;2.6 std::atomic<T*>2.7 标准整数原子类型2.8 std::atomic&…

【Flink】-- flink新版本发布:v2.0-preview1

目录 1、简介 2、非兼容变更 2.1、API 2.2、连接器适配计划 2.3、配置 2.4、其它 3、重要新特性 3.1、存算分离状态管理 3.2、物化表 3.3、批作业的自适应执行 3.4、流式湖仓 4、附加 4.1、非兼容性的 api 程序变更 4.1.2、Removed Classes # 4.1.3、Modified Cl…

ffmpeg+D3D实现的MFC音视频播放器,支持录像、截图、音视频播放、码流信息显示等功能

一、简介 本播放器是在vs2019下开发&#xff0c;通过ffmpeg实现拉流解码功能&#xff0c;通过D3D实现视频的渲染功能。截图功能采用libjpeg实现&#xff0c;可以截取jpg图片&#xff0c;图片的默认保存路径是在C:\MYRecPath中。录像功能采用封装好的类Mp4Record实现&#xff0c…

webpack指南

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;webpack篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来webpack篇专栏内容:webpack-指南 概念 中文&#xff1a; webpack | webpack中文文档 | webpack中文网 英文&…

把越南语翻译成中文一般用什么翻译工具?《越南语翻译通》App或许能满足你的技术痛点需求!

在多语言交流日益频繁的今天&#xff0c;掌握越南语对于商务、旅游或学术交流都是一项重要技能。《越南语翻译通》App应运而生&#xff0c;旨在通过技术手段简化越南语学习和翻译过程&#xff0c;满足用户在不同场景下的需求。 核心技术 《越南语翻译通》App采用了先进的自然语…

Android Framework AMS(16)进程管理

该系列文章总纲链接&#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节主要解读AMS 进程方面的知识。关注思维导图中左上侧部分即可。 我们本章节主要是对Android进程管理相关知识有一个基本的了解。先来了解下L…

Rust Struct 属性初始化

结构体是用户定义的数据类型&#xff0c;其中包含定义特定实例的字段。结构有助于实现更容易理解的抽象概念。本文介绍几种初始化结构体对象的方法&#xff0c;包括常规方法、Default特征、第三方包实现以及构建器模式。 Struct声明与初始化 struct Employee {id: i32,name: …

Vue全栈开发旅游网项目(10)-用户管理后端接口开发

1.异步用户登录\登出接口开发 1.设计公共响应数据类型 文件地址&#xff1a;utils/response404.py from django.http import JsonResponseclass BadRequestJsonResponse(JsonResponse):status_code 400def __init__(self, err_list, *args, **kwargs):data {"error_c…

数据结构:队列

目录 概念与结构底层结构的选择队列的实现队列头文件&#xff08;queue.h&#xff09;队列初始化队列的销毁入队列检查队列是否为空出队列查询队列第一个数据查询队列末尾数据查询队列有效数据个数代码试运行 概念与结构 概念&#xff1a;只允许在⼀端进行插⼊数据操作&#x…

Clickhouse集群新建用户、授权以及remote权限问题

新建用户 create user if not exists user on cluster 集群名称 IDENTIFIED WITH plaintext_password BY 密码;给用户授查询、建表、删表的权限 GRANT create table,select,drop table ON 数据库实例.* TO user on cluster 集群名称 ;再其他节点下用户建本地表成功&#…

JavaWeb--MySQL

1. MySQL概述 首先来了解一下什么是数据库。 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 像我们日常访问的电商网站京东&#xff0c;企业内部的管理系统OA、ERP、CRM这类的系统&#xff0c;以及大家每天都会刷的头条、抖音…

i春秋-SQLi(无逗号sql注入,-- -注释)

练习平台地址 竞赛中心 题目描述 后台有获取flag的线索应该是让我们检查源码找到后台 题目内容 空白一片 F12检查源码 发现login.php 访问login.php?id1 F12没有提示尝试sql注入 常规sql注入 //联合注入得到表格列数 1 order by 3 # 1 union select 1,2,3 #&#xff08…