leetCode 309.买卖股票的最佳时机含冷冻期 动态规划 + 滚动数组

news2025/1/4 17:34:19

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

给定一个整数数组prices,其中第  prices[i] 表示第 i 天的股票价格 。​设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: prices = [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

示例 2:

输入: prices = [1]
输出: 0

>>思路和分析

相对于动态规划:leetCode 122.买卖股票的最佳时机 II ,本题加上了一个冷冻期

在leetCode 122.买卖股票的最佳时机 II中有两个状态持有股票后的最多现金,和不持有股票的最多现金

>>动规五部曲

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

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

>>四个状态分析:

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

问题(O_O)?思考:“今天卖出股票”,在本题中为什么要单独列出这个状态呢?

是因为本题中有冷冻期而冷冻期的前一天,只能是“今天卖出股票”状态,如果是“不持有股票状态”就会很模糊,这是因为它不一定是卖出股票的操作。

2.确定递推公式

① 状态一(持有股票状态): dp[i][0],有两个具体操作:

  • 操作一:前一天就是持有股票状态(状态一)dp[i][0] = dp[i-1][0];
  • 操作二:今天买入了,有两种情况
    • 前一天是保持卖出股票的状态(状态二),dp[i-1][1]-prices[i];
    • 前一天是冷冻期(状态四)dp[i-1][3] - prices[i];

那么dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i],dp[i-1][3]-prices[i]);

② 状态二(保持卖出股票的状态):dp[i][1],有两个具体操作:

  • 操作一:前一天就是保持卖出股票的状态(状态二)dp[i][1] = dp[i-1][1];
  • 操作二:前一天就是冷冻期(状态四)dp[i][1] = dp[i-1][3];

那么dp[i][1] = max(dp[i-1][1],dp[i-1][3]);

③ 状态三(今天卖出股票):dp[i][2],只有一个操作:

  • 昨天一定是持有股票状态(状态一),那么今天才可以卖出

那么dp[i][2] = dp[i-1][0] + prices[i];

④ 状态四(冷冻期状态):dp[i][3],只有一个操作:

  • 昨天一定是卖出了股票(状态三),那么今天我就进入了冷冻期状态

那么dp[i][3] = dp[i-1][2];

综上分析,递推代码如下:

dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], 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];

3.dp数组初始化

第 0 天的初始化:

① 状态一(持有股票状态)dp[0][0] = -prices[0],表示一定是当天买入股票

② 状态二(保持卖出股票状态):很难从其定义来明确应初始为多少,那么此种情况我们就看递推公式需要给它初始成什么数值。例如:i = 1,在第 i 天买入股票,那么递归公式中需要计算

  • dp[i-1][1] - prices[i],即dp[0][1]-prices[1]

那么dp[0][1]只能初始为0,若初始为其他数值,则第1天买入股票后手里所剩的现金就不对了

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

④ 状态四(冷冻期状态),同上分析,dp[0][3]也初始化为0

vector<vector<int>> dp(n, vector<int>(4, 0));
dp[0][0] -= prices[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++) {
            dp[i][0] = max(dp[i - 1][0], max(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]));
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

其实,空间复杂度可以优化,定义一个dp[2][4]大小的数组就可以了,就保存前一天的当前的状态

>>优化空间复杂度

class Solution {
public:
    // 动态规划 滚动数组来节省空间
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        vector<vector<int>> dp(2,vector<int>(4,0));
        dp[0][0] = -prices[0];
        for(int i=1;i<len;i++) {
            dp[i % 2][0] = max(dp[(i-1) % 2][0],max(dp[(i-1) % 2][1] - prices[i],dp[(i-1) % 2][3] - prices[i]));
            dp[i % 2][1] = max(dp[(i-1) % 2][1],dp[(i-1) % 2][3]);
            dp[i % 2][2] = dp[(i-1) % 2][0] + prices[i];
            dp[i % 2][3] = dp[(i-1) % 2][2];
        }
        return max(dp[(len-1) % 2][1],max(dp[(len-1) % 2][2],dp[(len-1) % 2][3]));
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

参考和推荐文章、视频

代码随想录 (programmercarl.com)

动态规划来决定最佳时机,这次有冷冻期!| LeetCode:309.买卖股票的最佳时机含冷冻期_哔哩哔哩_bilibili

来自代码随想录的课堂截图:

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

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

相关文章

排序篇(四)----归并排序

排序篇(四)----归并排序 1.归并(递归) 基本思想&#xff1a; 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到…

【Linux】UDP的服务端 + 客户端

文章目录 &#x1f4d6; 前言1. TCP和UDP2. 网络字节序2.1 大小端字节序&#xff1a;2.2 转换接口&#xff1a; 3. socket接口3.1 sockaddr结构&#xff1a;3.2 配置sockaddr_in&#xff1a;3.3 inet_addr&#xff1a;3.4 inet_ntoa&#xff1a;3.5 bind绑定&#xff1a; 4. 服…

【VR】【unity】如何在VR中实现远程投屏功能?

【背景】 目前主流的VD应用,用于娱乐很棒,但是用于工作还是无法效率地操作键鼠。用虚拟键盘工作则显然是不现实的。为了让自己的头显能够起到小面积代替多显示屏的作用,自己动手开发投屏VR应用。 【思路】 先实现C#的投屏应用。研究如何将C#投屏应用用Unity 3D项目转写。…

FFmpeg 命令:从入门到精通 | ffplay 播放控制选项

FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项选项表格图片 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项 选项表格 项目说明Q&#xff0c;Esc退出播放F&#xff0c;鼠标左键双击全…

计算机网络分层结构

一、OSI参考模型(法定标准) 1.由国际标准化组织(ISO)提出的开放系统互连(OSI)参考模型 2.OSI七层结构&#xff1a; 3.通信过程&#xff1a; 4.各层功能 应用层-能和用户交互产生网络流量(需要联网)的程序&#xff0c;常见协议有文件传输(FTP)、电子邮件(SMTP)、万维网(HTTP)…

MASM32配置问题

1. 总述 当你用masm32 SDK出现类似下面的错误情况: cannot open file :windows.inc这说明你的汇编器无法找到windows.inc这个头文件, 有3种解决方法 2. 解决方法 a. 使用绝对路径 直接把需要的inc头文件或者lib库文件的绝对路径包含进去, 问题就解决了 .586 .model flat,…

【Java 进阶篇】MySQL多表关系详解

MySQL是一种常用的关系型数据库管理系统&#xff0c;它允许我们创建多个表格&#xff0c;并通过各种方式将这些表格联系在一起。在实际的数据库设计和应用中&#xff0c;多表关系是非常常见的&#xff0c;它能够更好地组织和管理数据&#xff0c;实现数据的复杂查询和分析。本文…

Heptabase 究竟好在哪儿?

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; Heptabase 1.0 正式版发布&#xff0c;你可以免费尝试了。 赞誉 我因为研究各种知识管理工具&#xff0c;常年混迹在不同的社区、群组与论坛中…

Python日期的加减等操作

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 日期输出格式化 所有日期、时间的api都在datetime模块内。 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都…

《MySQL高级篇》十六、主从复制

文章目录 1、主从复制概述1.1 如何提升数据库并发能力1.2 主从复制的作用 2、主从复制的原理2.1 原理剖析2.2 复制的基本原则 3、一主一从架构搭建3.1 准备工作3.2 主机配置文件3.3 从机配置文件3.4 主机&#xff1a;建立账户并授权3.5 从机&#xff1a;配置需要复制的主机3.6 …

UE5.1编辑器拓展【二、脚本化资产行为,快速更改资产名字,1.直接添加前缀或后缀2.通过资产类判断添加修改前缀】

目录 了解相关的函数 第一种做法&#xff1a;自定义添加选择资产的前缀或后缀 代码 效果 第二种做法&#xff1a;通过映射来获取资产类型添加前缀和修改前缀 映射代码 代码 效果 在之前一章中&#xff0c;我们创建了插件&#xff0c;用来扩展编辑器的使用&#xff1a; …

福利!这两款我自制的免费配色工具你领到了吗?

​前两天刚入职&#xff0c;还没干过啥活儿&#xff0c;就迎来了中秋3天国庆7天总共8天的假期&#xff0c;美滋滋。 在这么喜庆的日子里&#xff0c;我觉得大家应该也无心科研&#xff0c;所以不如给大家发点儿福利&#xff0c;继续乐呵乐呵。 当然&#xff0c;说是福利&…

Redis代替session 实现登录流程

Redis代替session 实现登录流程 如果使用String&#xff0c;他的value&#xff0c;用多占用一点空间&#xff0c;如果使用哈希&#xff0c;则他的value中只会存储他数据本身&#xff0c;如果不是特别在意内存&#xff0c;其实使用String就可以 设计key的具体细节 在设计这个k…

如何在Cocos中绘制一面国旗祝祖国生日快乐、繁荣昌盛

引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 74年风雨兼程、74载山河巨变&#xff0c;我们一起来祝福伟大的祖国生日快乐、繁荣昌盛&#xff01;我爱你中国&#xff01; 本文主要演示在Cocos中绘制一面国旗&#xff0c;用代码去表达…

【Java每日一题】— —第十七题:杨辉三角(等腰三角形)。(2023.10.01)

&#x1f578;️Hollow&#xff0c;各位小伙伴&#xff0c;今天我们要做的是第十七题。 &#x1f3af;问题&#xff1a; 第一步:动态初始化 第二步:求各元素的值 第三步:遍历输出 测试结果如下&#xff1a; &#x1f3af; 结果&#xff1a; public class yanghui {public sta…

10.1 国庆节小任务

目录 select实现服务器并发 服务器 客户端 运行现象 select实现服务器并发 服务器 #include<myhead.h>#define PORT 8888 //1024~49151 #define IP "192.168.1.104" //ifconfig查看本机IPint main(int argc, const char *argv[]) {//创建流式…

1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计

项目完整版在&#xff1a; 一、socket模块&#xff1a;套接字模块 二、提供的功能 Socket模块是对套接字操作封装的一个模块&#xff0c;主要实现的socket的各项操作。 socket 模块&#xff1a;套接字的功能 创建套接字 绑定地址信息 开始监听 向服务器发起连接 获取新连接 …

WPF 02

Grid容器 分行和分列 <Grid><Grid.RowDefinitions><!--2*&#xff1a;此行是下面一行的两倍--><RowDefinition Height"2*"/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/>…

[管理与领导-107]:IT人看清职场中的隐性规则 - 4 - 职场话术:其实是同一个意思,只是换一种了说法,效果不同,小心被套路

目录 前言&#xff1a; 一、套路和核心思想 1.1 核心思想 1.2 基本原则&#xff1a;让听话者舒服 二、消极变积极的说法 》 自足当下&#xff0c;展望未来 三、委婉拒绝 四、不想接受某项任务 五、正面、让人舒服的表达方式 六、其他 七、职场话术128条&#xff1a;…

ssm+vue的4S店预约保养管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的4S店预约保养管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…