Day51【动态规划】309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

news2024/11/24 19:34:41

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

力扣题目链接/文章讲解 

视频讲解 

记住昨天的回顾总结提到的:应该灵活利用 dp 数组的下标描述所有状态  

动态规划五部曲

1、确定 dp 数组下标及值含义

dp[i][j],第 i 天状态为 j,所剩的最多现金为 dp[i][j]

这样,通过两个下标,能够描述在某天及当天的股票持有状态

每天具体可以区分出如下四个状态:

  • 状态一:持有股票状态(今天买入股票,或者是之前就买入了股票然后没有操作,一直持有)
  • 非冷冻期且不持有股票状态,需区分两种卖出股票状态(区分的原因:为了推冷冻期状态)
    • 状态二:保持卖出股票的状态(两天前就卖出了股票,度过一天冷冻期。或者是前一天就是卖出股票状态,一直没操作)
    • 状态三:今天卖出股票
  • 状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天!

dp[i][0]:下标表示在第 i 天,持有股票的状态,值为当前状态下的最大利润

dp[i][1]:下标表示在第 i 天,保持卖出股票的状态,值为当前状态下的最大利润

dp[i][2]:下标表示在第 i 天,当天卖出股票的状态,值为当前状态下的最大利润

dp[i][3]:下标表示在第 i 天,当前为冷冻期的状态,值为当前状态下的最大利润

2、确定递推公式 

需要分别思考 dp[i][0]、dp[i][1]、dp[i][2]、dp[i][3] 应该怎么推

dp[i][0]:表示在第 i 天,持有股票的情况下的最大利润,我们需要考虑怎么从前一天转移到当前状态

  • 可能在第 i - 1 天就已经持有股票了,即 dp[i - 1][0],到了第 i 天只需要保持状态不操作
  • 可能在第 i - 1 天非冷冻期且不持有股票,那么我们可以在第 i 天买入,即 dp[i - 1][1] - prices[i]
  • 可能在第 i - 1 天为冷冻期,我们也可以在第 i 天买入,即 dp[i - 1][3] - prices[i]

因为需要最大利润,所以 dp[i][0] = max(dp[i - 1][0], dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i]) 

dp[i][1]:表示在第 i 天,保持卖出股票的情况下的最大利润

  • 可能在第 i - 1 天就已经保持卖出股票的状态了,即 dp[i - 1][1]
  • 可能在第 i - 1 天为冷冻期,那么到了第 i 天就为非冷冻期且卖出股票的状态,即 dp[i - 1][3]

因为需要最大利润,所以 dp[i][1] = max(dp[i - 1][1], dp[i - 1][3])

dp[i][2]:表示在第 i 天,当天卖出股票的情况下的最大利润

这种只可能是在 i - 1 天持有股票的情况下,再在第 i 天卖出,即 dp[i][2] = dp[i - 1][0] + prices[i]

dp[i][3]:表示在第 i 天,当天为冷冻期的情况下的最大利润

这种只可能是在第 i - 1 天当天卖出的情况下,到了第 i 天才为冷冻期,即 dp[i][3] = dp[i - 1][2] 

3、初始化 dp 数组

根据递推公式,第 i 天的 dp 值都是从第 i - 1 天的 dp 值推导出来的,我们需要初始化dp[0][j]

如果是持有股票状态(状态一)那么:dp[0][0] = -prices[0],一定是当天买入股票

保持卖出股票状态(状态二),这里其实从 「状态二」的定义来说 ,很难明确应该初始多少,这种情况我们就看递推公式需要我们给他初始成什么数值

如果 i 为 1,第 1 天买入股票,那么递归公式中需要计算 dp[i - 1][1] - prices[i] ,即 dp[0][1] - prices[1],那么大家感受一下 dp[0][1] (即第0天的状态二)应该初始成多少,只能初始为0。如果初始为其他数值,是我们第1天买入股票后手里还剩的现金数量就不对了

今天卖出了股票(状态三),同上分析,dp[0][2]初始化为0,dp[0][3]也初始为0

对于通过定义难以确定如何初始化的情况,应该结合递推公式确定如何初始化 

4、确定遍历顺序

从递推公式可以看出 dp[i] 都是由 dp[i - 1] 推导出来的,那么一定是从前向后遍历 

5、打印 dp 数组验证

代码如下

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if (n == 0) return 0;
        vector<vector<int>> dp(n, vector<int>(4, 0));
        dp[0][0] -= prices[0]; // 持股票
        for (int i = 1; i < n; i++) {   // i为0时已经被初始化过了,从i为1开始遍历填充dp数组
            // 四种情况
            dp[i][0] = max(max(dp[i - 1][0], dp[i - 1][3] - prices[i]), dp[i - 1][1] - 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[n - 1][3], max(dp[n - 1][1], dp[n - 1][2]));
    }
};

注意,最后的结果一定是到达最后一天,且不持有股票状态或冷冻期状态

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

力扣题目链接/文章讲解 

视频讲解 

本题假设在卖出的时候支付手续费 

动态规划五部曲!

1、确定 dp 数组下标及值的含义 

先想想本题 dp 应该怎么定义,别忘了之前说的,dp 数组的下标能够表示状态

在股票问题中,某个状态需要描述在某天,及是否持有股票

因此我们定义 dp 数组下标及值含义:

dp[i][0]:下标表示在第 i 天,未持有股票,值表示第 i 天未持有股票所得最多现金

dp[i][1]:下标表示在第 i 天,持有股票,值表示第 i 天持有股票所得最多现金

通过第一个下标 i 描述在哪一天,第二个下标为 0 或 1 描述在该天未持有或持有股票,这样通过两个下标就能够描述所有的状态了

2、确定递推公式

分别思考 dp[i][0] 和 dp[i][1] 分别应该怎么推

dp[i][0]:需要求第 i 天未持有股票所得最多现金,要考虑怎么转移到第 i 天未持有股票的这种状态

可能是在第 i 天卖出了股票,所得现金就是昨天持有股票,然后今天卖出股票后所得现金,注意考虑卖出需要支付手续费,即:dp[i - 1][1](昨天持有股票)+ prices[i](今天卖出股票)- fee
可能是在第 i - 1 天就未持有股票,那么就保持现状,所得现金就是昨天未持有股票的所得现金,即:dp[i - 1][0](昨天未持有股票)
因为求的最多现金,即 dp[i][0] = max(dp[i - 1][1] + prices[i] - fee[i], dp[i - 1][0]) 

同理,dp[i][1]:

可能是在第 i 天买入股票,所得现金为 dp[i - 1][0](昨天未持有股票)- prices[i](今天买入股票)(因为一只股票可以买卖多次,所以当第 i 天买入股票的时候,所持有的现金需要考虑之前买卖过的利润)
可能是在第 i - 1 天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金,即:dp[i - 1][1](昨天持有股票)
因为求的最多现金,即 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1])  

3、dp 数组初始化

从递推公式看出,求某一天 dp 需要知道其前一天的 dp 值,即都是要从dp[0][0]和dp[0][1]推导出来

那么dp[0][0]表示第 0 天未持有股票,不持有股票现金就是 0,所以 dp[0][0] = 0

dp[0][1]表示第 0 天持有股票,持有股票一定是在第 0 天买入了股票,所以 dp[0][1] = -prices[0]

4、确定遍历顺序

从递推公式可以看出 dp[i] 都是由 dp[i - 1] 推导出来的,那么一定是从前向后遍历

5、打印 dp 数组验证

代码如下

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        
        vector<vector<int> > dp(prices.size(), vector<int>(2));

        dp[0][0] = 0;   // 第0天不持股
        dp[0][1] = -prices[0];  // 第0天买入股票

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

        return max(dp[prices.size() - 1][0], dp[prices.size() - 1][1]);
    }
};

滚动数组优化的代码略 

本题和 122.买卖股票的最佳时机II 的区别就是这里需要多一个减去手续费的操作 


回顾总结 

应该灵活利用 dp 数组的下标描述所有状态

对于定义难以确定如何初始化的情况,应该结合递推公式确定如何初始化 

 

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

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

相关文章

2023年中国AI芯片行业市场现状及未来发展趋势预测

2023年AI芯片报告汇总了60家国产AI芯片厂商&#xff0c;大致按如下应用类别进行归类&#xff1a;云端加速、智能驾驶、智能安防、智能家居、智能穿戴、其它AIoT。对于每一家筛选的公司&#xff0c;我们从主要产品、核心技术、应用场景、市场竞争力、发展里程碑等方面对公司进行…

vue做一个一直自增加载且永远不会超过百分之九十九的数值 制造正在加载假象

我们在src跟目录下创建一个utils目录下面创建一个continuousLoading.js 参考代码如下 let value 0;export default function(callback) {const timer setInterval(() > {if (callback&&(value || value 0)&&value < 99) {value 1;callback(value);}…

一篇文章搞定《Android事件分发》

一篇文章搞定《Android事件分发》 什么是事件分发MotionEvent事件事件如何从屏幕到APPInputManagerServiceWindowManagerServiceWindow小结 事件如何从APP到达对应页面第一步&#xff1a;分类第二步&#xff1a;送去Activity后续的传递小结&#xff1a; 页面的事件分发整个流程…

道岔外锁闭装置介绍

简述 道岔外锁闭装置是一种能可靠地锁闭尖轨和基本轨的器械。它能有效地克服尖轨在密贴时的转换阻力&#xff0c;即使连接杆折断&#xff0c;外锁闭装置仍在起着锁闭作用。外锁闭能够隔离列车通过时对转换设备的振动和冲击&#xff0c;提高转换设备寿命和可靠性。 产品分类 …

Kubernetes Dashboard + Ingress 及其 yaml 文件分析

概述 记录部署Dashboard Ingress的具体过程及其 yaml 文件分析 Dashboard Yaml # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the Li…

【C++】类和对象的应用案例 2 - 点和圆的关系

目录 1、缘起 2、分析 3、示例代码 4、代码优化 4.1、point.h 4.2、point.c 4.3、circle.h 4.4、circle.c 4.4、main.c 5、总结 1、缘起 在 C 中&#xff0c;类和对象可以用来构建有趣的应用程序。一个生动形象且吸引人的案例是点和圆的关系。通过创建一个 Po…

C++内存管理 (new、delete)知识点+完整思维导图+实操图+深入细节通俗易懂建议收藏

绪论 我成功是因为我有决心&#xff0c;从不踌躇。——拿破仑 本章是关于c内存管理的文章&#xff0c;字数不多&#xff0c;内容简单&#xff0c;希望对你有所帮助&#xff01;&#xff01; 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看&#xff09;。 附&a…

【redis基础】redis的十大数据类型

前言 接受虚竹哥的建议&#xff0c;后续将发布redis的系列文章 本篇文章针对有关Redis7数据类型的的使用率较高的操作进行讲解&#xff0c;有关Redis7中数据类型的全部操作请查阅&#xff1a;Commands | Redis 上一篇文章&#xff1a;初识redis【redis的安装使用与卸载】_努…

Java --- 云尚办公之Activiti7

目录 一、工作流 1.1、什么是工作流 1.2、工作流引擎 1.3、常见工作流引擎 二、 Activiti7概述 2.1、Activiti介绍 2.2、建模语言BPMN 2.3、 Activiti使用流程 三、 Activiti使用 3.1、部署流程工具 3.2、画出流程图并放入项目中 3.3、流程定义部署 3.4、启动流程…

要闻 | 自然资源部实景三维建设与城市精细化治理工程技术创新中心揭牌仪式暨第二季度工作推进会顺利召开

2023年5月16日上午&#xff0c;全国首个实景三维领域部级工程技术创新中心——自然资源部实景三维建设与城市精细化治理工程技术创新中心&#xff08;以下称“中心”&#xff09;在武汉大势智慧科技有限公司举行了揭牌仪式&#xff0c;并在大势会议室顺利召开了中心第二季度工作…

19-02 基于业务量级的架构技术选型演进

从零开始——单服务应用 单体应用技术选型 &#xff08;GitHub、Gitee…&#xff09;搜索是否有线程的产品用最熟悉的技术&#xff0c;最快的速度上线如果有经费&#xff1a;考虑商业化解决方案 个人小程序怎么做技术选型的 搜索是否有快速搭建下程序的软件技术选型 后端技…

PX4从放弃到精通(二十五):EKF2

文章目录 前言一、主程序二、update()二、predictState()三、controlFusionModes()四、controlGpsFusion五、fuseGpsVelPos()六、fuseHorizontalVelocity()七、fuseVelPosHeight()八、calculateOutputStates()前言 PX4 1.13.2 PX4 ekf的传感器数据放在FIFO的环形缓冲区中,每…

智能综合交通(水运、航空)主题汇总(附下载链接)

根据我国现行的交通运输体制&#xff0c;公路以外的交通运输称为综合交通运输形式&#xff0c;包括铁路、航空和水运等。本部分包括航空和水运运输&#xff08;铁路部分另外单独列出&#xff09;。 智慧水运、航道、港口 &#xff08;至2023年05月23日&#xff09; 湛江市综合交…

容器编排器们的自我介绍

哈喽大家好&#xff0c;我是咸鱼 咸鱼在《一文带你了解容器技术的前世今生》有介绍过容器技术的由来以及Docker项目的发展 我们知道&#xff0c;Docker 及其他容器技术能够极大地简化应用程序的部署&#xff0c;做到了”开箱即用“ 俗话说&#xff1a;”凡是具有两面性“。容…

OSPF 5种报文、状态机、邻居建立的过程

OSPF 5种报文、状态机、邻居建立的过程 一、OSPF的5种报文二、OSPF状态机三、OSPF建立的过程 一、OSPF的5种报文 Hello 用于发现邻居&#xff0c;维持邻居的状态 DD DD报文有确定设备主从&#xff0c;同步DD序列号 包含着LSA的头部信息&#xff0c;有同步LSDB数据库的作用 LSA…

云原生|Kubernetes Operator测试实例

目录 一、主要代码介绍 &#xff08;一&#xff09;变量定义&#xff1a; &#xff08;二&#xff09;测试程序入口 &#xff08;三&#xff09;before函数 &#xff08;四&#xff09;after函数 二、实际测试 &#xff08;一&#xff09;块划分 &#xff08;二&#x…

【数据分享】1997-2017 年中国市县级能耗与能效数据集

能源既关乎国家经济命脉&#xff0c;又影响人民生活水平&#xff01;能源相关的研究是各个行业的热门研究话题&#xff0c;能源相关的数据也是经常使用的数据&#xff01; 我们发现在figshare平台上分享有1997-2017 年我国市县级的能耗与能效数据&#xff0c;数据格式为Excel&…

CMake常用命令总结与练习

CMake常用命令总结 前言cmake_minimum_required (VERSION XX):CMake最低版本project (demo)&#xff1a;CMake工程名add_executable(main main.c):生成可执行文件aux_source_directory(dir var)&#xff1a;指定源文件放入变量set(val src):指定源文件放入变量include_director…

js闭包的简单应用

闭包的概念&#xff1a;有权访问其他函数的内部变量的函数 闭包是作用域运用的特殊场景。 注&#xff1a;js中自由变量的查找是在函数定义的地方向上级作用域查找&#xff0c;不是在执行的地方。 闭包的使用场景概况为两种&#xff0c;一种是函数作为参数被传递&#xff0c;一种…

面试官:MySQL自增主键一定是连续的吗?

测试环境&#xff1a; MySQL版本&#xff1a;8.0 数据库表&#xff1a;T &#xff08;主键id&#xff0c;唯一索引c&#xff0c;普通字段d&#xff09; 如果你的业务设计依赖于自增主键的连续性&#xff0c;这个设计假设自增主键是连续的。但实际上&#xff0c;这样的假设是错的…