简单多状态dp第三弹 leetcode -买卖股票的最佳时机问题

简单多状态dp第三弹 leetcode -买卖股票的最佳时机问题


 

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

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

分析:

使用动态规划解决

状态表示:

由于有「买入」「可交易」「冷冻期」三个状态,因此我们可以选择用三个数组,其中:
dp[i][0] 表示:第 i 天结束后,处于「买入」状态,此时的最大利润。
dp[i][1] 表示:第 i 天结束后,处于「可交易」状态,此时的最大利润。
dp[i][2] 表示:第 i 天结束后,处于「冷冻期」状态,此时的最大利润。

状态转移方程:

1.处于买入状态的时候,我们现在有股票,此时不能买股票,只能继续持有股票,或者卖
出股票;

2.处于卖出状态的时候:

如果在冷冻期,不能买入。

如果 不在冷冻期,才能买入。

画出状态图

根据状态图可以得出:

买入->买入:什么都不干

买入->卖出:买入股票

对应代码:a[i]=max(a[i-1],c[i-1]-prices[i-1]);

卖出->卖出:什么都不干

卖出->冷冻期:卖出股票

对应代码:b[i]=max(b[i-1],a[i-1]+prices[i-1]);

冷冻期->冷冻期:什么都不干

冷冻期->买入:冷冻期结束

对应代码:c[i]=max(c[i-1],b[i-1]);

代码:

class Solution { public: int maxProfit(vector<int>& prices) { int n=prices.size(); vector<int>a(n+1);//买入 vector<int>b(n+1);//卖出 vector<int>c(n+1);//冷冻 a[0]-=prices[0]; for(int i=1;i<=n;i++) { a[i]=max(a[i-1],c[i-1]-prices[i-1]); b[i]=max(b[i-1],a[i-1]+prices[i-1]); c[i]=max(c[i-1],b[i-1]); } return max(b[n],c[n]);//从卖出和冷冻期中选出最大值,因为买入状态肯定不是最大值,因为还有股票没有卖出。 } };


714. 买卖股票的最佳时机含手续费

 买卖股票的最佳时机含手续费

分析:

使用动态规划解决

 

与 买卖股票的最佳时机含冷冻期 问题相似,我们直接画出状态图写状态方程。

状态图:

 

买入->买入:什么都不干

买入->卖出:买入股票

对应代码:a[i]=max(a[i-1],c[i-1]-prices[i-1]);

卖出->卖出:什么都不干

卖出->买入:卖出股票并支付手续费

对应代码:b[i]=max(b[i-1],a[i-1]+prices[i-1]-fee);

代码:

class Solution { public: int maxProfit(vector<int>& prices, int fee) { int n=prices.size(); vector<int>a(n+1);//买入 vector<int>b(n+1);//卖出 a[0]-=prices[0]; for(int i=1;i<=n;i++) { a[i]=max(a[i-1],b[i-1]-prices[i-1]); b[i]=max(b[i-1],a[i-1]+prices[i-1]-fee); } return b[n]; } };


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

买卖股票的最佳时机 III

状态表示:

这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求,定义一个状态表示:
由于有「买入」「可交易」两个状态,因此我们可以选择用两个数组。但是这道题里面还有交易次
数的限制,因此我们还需要再加上一维,用来表示交易次数。其中:

▪ f[i][j] 表示:第 i 天结束后,完成了 j 次交易,处于「买入」状态,此时的最大利
润;
▪ g[i][j] 表示:第 i 天结束后,完成了 j 次交易,处于「卖出」状态,此时的最大利
润。

状态转移方程:
 

A.对于 f[i][j] ,我们有两种情况到这个状态:


1. 在 i - 1 天的时候,交易了 j 次,处于「买入」状态,第 i 天啥也不干即可。此时最
大利润为: f[i - 1][j] ;


2. 在 i - 1 天的时候,交易了 j 次,处于「卖出」状态,第 i 天的时候把股票买了。此
时的最大利润为: g[i - 1][j] - prices[i] 。


综上,我们要的是「最大利润」,因此是两者的最大值: f[i][j] = max(f[i - 1][j],
g[i - 1][j] - prices[i]) 。

B.对于 g[i][j] ,我们也有两种情况可以到达这个状态:


1.在 i - 1 天的时候,交易了 j 次,处于「卖出」状态,第 i 天啥也不干即可。此时的
最大利润为: g[i - 1][j] ;


2.在 i - 1 天的时候,交易了 j - 1 次,处于「买入」状态,第 i 天把股票卖了,然
后就完成了 j 比交易。此时的最大利润为: f[i - 1][j - 1] + prices[i] 。但
是这个状态不一定存在,要先判断一下。



综上,我们要的是最大利润,因此状态转移方程为:
g[i][j] = g[i - 1][j];
if(j >= 1) g[i][j] = max(g[i][j], f[i - 1][j - 1] + prices[i]);

代码:

class Solution { public: int maxProfit(vector<int>& prices) { const int INF=0x3f3f3f3f; int n=prices.size(); vector<vector<int>>f(n+1,vector<int>(3,-INF));//买 vector<vector<int>>g(n+1,vector<int>(3,-INF));//卖 f[0][0]=-prices[0]; g[0][0]=0; for(int i=1;i<n;i++) { for(int j=0;j<3;j++) { f[i][j]=max(f[i-1][j],g[i-1][j]-prices[i]); g[i][j]=g[i-1][j]; if(j-1>=0) { g[i][j]=max(g[i][j],f[i-1][j-1]+prices[i]); } } } int ans=0; for(int i=0;i<3;i++) { ans=max(ans,g[n-1][i]); } return ans; } };

Read more

ExcelJS 使用教程 - 强大的 JavaScript Excel 处理库

ExcelJS 使用教程 - 强大的 JavaScript Excel 处理库 【免费下载链接】exceljs 项目地址: https://gitcode.com/gh_mirrors/exc/exceljs ExcelJS 是一个功能强大的 JavaScript 库,专门用于读取、操作和写入 Excel 电子表格数据,支持 XLSX 和 JSON 格式。它是一个开源项目,旨在提供一个简单而强大的接口来处理电子表格数据。 项目介绍 ExcelJS 是一个跨平台的 Excel 处理库,不仅可以在 Node.js 环境中使用,还支持浏览器环境,使其成为一个非常灵活的工具。它支持丰富的功能,包括单元格样式、公式、图表、图片插入、数据验证等高级功能。 快速开始

By Ne0inhk

JavaScript完全指南:从入门到精通

一、JavaScript基础概念 1.1 什么是JavaScript? JavaScript(简称JS)是一种轻量级的解释型编程语言,主要用于为网页添加交互性。它是Web开发的三大核心技术之一(HTML、CSS、JavaScript)。 1.2 JavaScript的历史 * 1995年:Brendan Eich在10天内创造了JavaScript,最初名为Mocha * 1996年:改名为LiveScript,最后定名为JavaScript * 1997年:ECMAScript标准建立 * 2009年:Node.js诞生,JS可在服务器端运行 * 2015年:ES6(ECMAScript 2015)发布,引入大量新特性 * 至今:持续发展和完善,每年都有新版本 1.3 JavaScript的特点 * 解释型语言:无需编译,直接在浏览器中执行 * 动态类型:变量类型在运行时确定 * 函数式编程:支持高阶函数、闭包等特性 * 面向对象:

By Ne0inhk
【Java 开发日记】阻塞队列有哪些?拒绝策略有哪些?

【Java 开发日记】阻塞队列有哪些?拒绝策略有哪些?

目录 阻塞队列有哪些? 拒绝策略有哪些? 面试回答 阻塞队列有哪些? 在Java的java.util.concurrent包里面,阻塞队列的实现挺多的,我们可以根据它的功能和结构来记,主要分这么几类: 1. 按容量划分: * 有界队列: 就是队列有固定的容量。 * ArrayBlockingQueue: 最经典的一个,底层是数组,创建时必须指定大小。它的生产和消费用同一把锁,性能相对稳定。 * LinkedBlockingQueue: 底层是链表,它既可以是有界的(构造时指定容量),也可以默认是无界的(默认是Integer.MAX_VALUE,几乎相当于无界)。它的生产和消费用了两把锁,在高并发场景下吞吐量通常比ArrayBlockingQueue更高。 * 无界队列: 理论上是无限的,只要内存够就能一直放。 * PriorityBlockingQueue: 一个支持优先级排序的无界队列。元素必须实现Comparable接口,或者构造时传入Comparator。它出队的顺序是按优先级来的,不是先进先出 * DelayQueue: 一个很特殊的队

By Ne0inhk
【JAVA 进阶】深入理解Sentinel:分布式系统的流量守卫者

【JAVA 进阶】深入理解Sentinel:分布式系统的流量守卫者

文章目录 * 前言 * 第一章 初识Sentinel:分布式系统的流量安全阀 * 1.1 什么是Sentinel? * 1.2 为什么需要Sentinel? * 1.2.1 分布式系统的稳定性痛点 * 1.2.2 Sentinel的核心价值 * 1.3 Sentinel的核心概念 * 1.3.1 资源 * 1.3.2 规则 * 1.3.3 插槽链(Slot Chain) * 1.3.4 令牌桶与漏桶算法 * 第二章 Sentinel环境搭建:从控制台到客户端 * 2.1 Sentinel Dashboard搭建 * 2.1.1

By Ne0inhk