LeetCode刷题复盘笔记—一文搞懂动态规划之309. 最佳买卖股票时机含冷冻期问题(动态规划系列第二十四篇)

news2024/10/3 0:29:21

今日主要总结一下动态规划的一道题目,309. 最佳买卖股票时机含冷冻期

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

Leetcode题目地址
题目描述:
给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

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

示例 2:

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

提示:

1 <= prices.length <= 5000
0 <= prices[i] <= 1000

本题重难点

这道题目相对于一文搞懂动态规划之122. 买卖股票的最佳时机 II问题本题加上了一个冷冻期

在一文搞懂动态规划之122. 买卖股票的最佳时机 II问题中有两个状态,持有股票后的最多现金,和不持有股票的最多现金。

动规五部曲,分析如下:

  1. 确定dp数组以及下标的含义
    dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。
    其实本题很多同学搞的比较懵,是因为出现冷冻期之后,状态其实是比较复杂度,例如今天买入股票、今天卖出股票、今天是冷冻期,都是不能操作股票的。 具体可以区分出如下四个状态:
    状态一:持有股票状态(今天买入股票,或者是之前就买入了股票然后没有操作)
    而卖出股票状态,这里就有两种卖出股票状态
    状态二:两天前就卖出了股票,度过了冷冻期,一直没操作,今天保持卖出股票状态
    状态三:今天卖出了股票
    状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天!

在这里插入图片描述
j的状态为:

0:状态一
1:状态二
2:状态三
3:状态四
很多题解为什么讲的比较模糊,是因为把这四个状态合并成三个状态了,其实就是把状态二和状态四合并在一起了。

从代码上来看确实可以合并,但从逻辑上分析合并之后就很难理解了,所以我下面的讲解是按照这四个状态来的,把每一个状态分析清楚。

注意这里的每一个状态,例如状态一,是买入股票状态并不是说今天已经就买入股票,而是说保存买入股票的状态即:可能是前几天买入的,之后一直没操作,所以保持买入股票的状态。

  1. 确定递推公式
    达到买入股票状态(状态一)即:dp[i][0],有两个具体操作:
    操作一:前一天就是持有股票状态(状态一),dp[i][0] = dp[i - 1][0]
    操作二:今天买入了,有两种情况
    前一天是冷冻期(状态四),dp[i - 1][3] - prices[i]
    前一天是保持卖出股票状态(状态二),dp[i - 1][1] - prices[i]
    所以操作二取最大值,即:max(dp[i - 1][3], dp[i - 1][1]) - prices[i]
    那么dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
    达到保持卖出股票状态(状态二)即:dp[i][1],有两个具体操作:
    操作一:前一天就是状态二
    操作二:前一天是冷冻期(状态四)
    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];
  1. dp数组如何初始化
    这里主要讨论一下第0天如何初始化。
    如果是持有股票状态(状态一)那么:dp[0][0] = -prices[0],买入股票所剩现金为负数。
    保持卖出股票状态(状态二),第0天没有卖出dp[0][1]初始化为0就行,
    今天卖出了股票(状态三),同样dp[0][2]初始化为0,因为最少收益就是0,绝不会是负数。
    同理dp[0][3]也初始为0。

  2. 确定遍历顺序
    从递归公式上可以看出,dp[i] 依赖于 dp[i-1],所以是从前向后遍历。

  3. 举例推导dp数组

以 [1,2,3,0,2] 为例,dp数组如下:
在这里插入图片描述

最后结果是取 状态二,状态三,和状态四的最大值,不少同学会把状态四忘了,状态四是冷冻期,最后一天如果是冷冻期也可能是最大值。

方法一、 动态规划未优化代码

C++代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(prices.size(), vector<int>(4, 0));
        //dp[i][j] 
        //j : 0. 持有股票 1. 保持卖出股票 2. 当天卖出股票 3. 冷冻期
        dp[0][0] = - prices[0];
        for(int i = 1; i < prices.size(); i++){
            dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1] - prices[i], dp[i - 1][3] - 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[prices.size() - 1][1], max(dp[prices.size() - 1][2], dp[prices.size() - 1][3]));
    }
};

方法二、 动态规划优化代码

从递推公式可以看出,dp[i]只是依赖于dp[i - 1]的状态。
那么我们只需要记录 当前天的dp状态和前一天的dp状态就可以了,可以使用滚动数组来节省空间,代码如下:

C++代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(2, vector<int>(4, 0));
        //dp[i][j]
        //j : 0. 持有股票 1. 保持卖出股票 2. 当天卖出股票 3. 冷冻期
        dp[0][0] = - prices[0];
        for(int i = 1; i < prices.size(); 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[(prices.size() - 1) % 2][1], max(dp[(prices.size() - 1) % 2][2], dp[(prices.size() - 1) % 2][3]));
    }
};

总结

动态规划
英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。
动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的

对于动态规划问题,可以拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

这篇文章主要总结了一些动态规划解决309. 最佳买卖股票时机含冷冻期问题,依然是使用动规五部曲,做每道动态规划题目这五步都要弄清楚才能更清楚的理解题目!

在买卖股票的最佳时机问题的整个系列题目中使用贪心算法仅仅可以解决某个具体场景的问题,但是并不通用,而动态规划思想解决买卖股票的最佳时机整个系列问题是通用连续递进的,最好掌握一下,并且最后给出了使用滚动数组优化空间复杂度的代码!
欢迎大家关注本人公众号:编程复盘与思考随笔
(关注后可以免费获得本人在csdn发布的资源源码)

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

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

相关文章

Python编程 函数的定义与参数

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.函数 1.函数例子 不会让代码重复的出现。CVout 2.函数介绍(熟悉) 3.…

如何在AdsPower中设置Oxylabs住宅代理和数据中心代理?

AdsPower是一款适用于Windows和Mac系统的浏览器管理工具&#xff0c;允许多用户登录。AdsPower的主要功能有多账户管理、浏览器指纹处理等。 集成操作流程 在官网&#xff08;www.adspower.com/download&#xff09;下载AdsPower并完成安装工作后&#xff0c;单击新建配置文件…

分布式文件系统之NFS

「分布式」是现在蛮流行的一个词&#xff0c;而其盛行&#xff0c;离不开底层网络通信能力的迅速发展。在文件系统这个领域&#xff0c;早期的分布式实现更多的是用来实现「共享」&#xff0c;而不是「容错」。传统的集中式文件系统允许单个系统中的多用户共享本地存储的文件&a…

SVG公众号排版 | GIF动图如何禁止循环播放?PS设置了也没用!

在SVG公众号排版中,我们经常使用到GIF动图,有些排版需求是想让GIF动图一直无限循环播放,也有其他排版需求是只想让GIF动图播放一次就停止了,这种情况我们可以通过Photoshop软件来设置GIF动图的播放次数,详见下图。 但是呢,也有一种情况,即使在Photoshop软件设置了GIF动图…

大话设计模型 Task02:策略、装饰、代理

目录一、简单工厂模式问题描述模式定义问题分析代码实现二、策略模式问题描述问题分析模式定义代码实现三、装饰模式问题描述问题分析模式定义代码实现四、代理模式问题描述问题分析模式定义代码实现五、工厂方法模式问题描述问题分析模式定义简单工厂 vs. 工厂方法代码实现一、…

上传项目代码到Github|Gitee

上传项目代码到Github|Gitee 文章目录上传项目代码到Github|Gitee1、前置准备1.1 Git 安装1.2 在 Git 中设置用户名1.2.1 为计算机上的每个存储库设置 Git 用户名1.2.2 为一个仓库设置 Git 用户名1.3 SSH免密登录1.4 Github创建一个新的仓库2、上传项目2.1 初始化本地库2.2 添加…

蓝桥杯入门即劝退(十六)查找元素范围(双解法)

欢迎关注点赞评论&#xff0c;共同学习&#xff0c;共同进步&#xff01; ------持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法&#xff0c;欢迎订阅专栏共同学习交流&#xff01; 你的点赞、关注、评论、是我创作的动力&#xff01; -------希望我的文章…

什么是制造业数字化转型?制造业数字化转型的核心与意义

对于生产制造企业来讲&#xff0c;当下如果不进行数字化转型的话&#xff0c;很大概率会被时代所抛弃的。为什么这么讲&#xff1f;因为在未来的很长一段时间&#xff0c;你可以充分了解到&#xff0c;数字化转型已然成为了制造业向前的主旋律。既然数字化势在必行&#xff0c;…

可以赚钱的副业项目,简单易上手兼职副业推荐

在当前的经济环境下&#xff0c;对每个人来说&#xff0c;仅仅依靠那点薪水生活是非常紧张的。为了改善你的生活&#xff0c;你需要找到其他赚钱的方法&#xff0c;在互联网上做兼职是一个不错的选择。 今天推荐几个普通人可以做的兼职副业&#xff0c;希望对大家有所帮助。 一…

微信公众号的文章可以修改几次?修改的步骤有哪些

许多小伙伴们在运营微信公众号的时候&#xff0c;可能会遇到过这些难题&#xff0c;在发布微信公众号之前检查没有检查好&#xff0c;导致有错字或者是错句。有的时候可能配图还会配错&#xff01; 今天伯乐网络传媒就给大家带来一些实用的东西&#xff0c;比如微信公众号可以…

深入理解 Python 的对象拷贝和内存布局

深入理解 Python 的对象拷贝和内存布局 前言 在本篇文章当中主要给大家介绍 python 当中的拷贝问题&#xff0c;话不多说我们直接看代码&#xff0c;你知道下面一些程序片段的输出结果吗&#xff1f; a [1, 2, 3, 4] b a print(f"{a } \t|\t {b }") a[0] 100…

微信小程序的自定义组件(1)

文章目录1. 自定义组件2. 组件样式3. 组件-数据、方法和属性4. 组件数据监听器5. 组件纯数据字段1. 自定义组件 Component(Object object) | 微信开放文档 (qq.com) 创建组件 在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建components->test文件夹在新建的componen…

第十二章 计算学习理论

12.1 基础知识 计算学习理论研究的关于通过计算来进行学习的理论。即关于机器学习的理论基础&#xff0c;其目的是分析学习任务的困难本质&#xff0c;为学习算法提供理论保证&#xff0c;并根据分析结果指导算法设计。 12.2 PAC学习 计算学习理论中最基本的是概率近似正确&…

点击化学染料DBCO-PEG-CY7.5|Cyanine7.5-PEG-DBCO|花青素Cyanine7.5

​DBCO-PEG-CY7.5点击化学染料其中Cy7.5 (Cyanine 7.5) 是一种发近红外&#xff08;NIR&#xff09;荧光的花青素荧光染料。根据磺化与否&#xff0c;分为普通Cy7.5和磺化Cy7.5&#xff0c;但常常统称为Cy7.5。 Cy7.5的消光系数高&#xff0c;荧光也很亮&#xff0c;并且对pH不…

为什么很多人转行学习Web前端技术?

为什么很多人转行学习Web前端技术?不管你是工人阶层还是服务行业&#xff0c;是否想过转行IT&#xff0c;转行IT后肯定会选择一门编程语言进行深入学习&#xff0c;很多转行的人基础都不是太好&#xff0c;不是科班出身&#xff0c;甚至有的是专科乃至中专&#xff0c;前端的H…

cuda学习笔记3——cuda常用内存相关函数及其使用示例

cuda学习笔记3——cuda常用内存相关函数及其使用示例常用的GPU内存函数cudaMalloc()cudaMemcpy()cudaFree()代码示例常用的GPU内存函数 cuda程序将系统区分成host和device&#xff0c;二者有各自的memory。kernel可以操作device memory&#xff0c;为了能很好的控制device端内…

软件测试人员去外包公司待遇怎么样?外包薪资高吗?

&#x1f4cc; 博客主页&#xff1a; 程序员二黑 &#x1f4cc; 专注于软件测试领域相关技术实践和思考&#xff0c;持续分享自动化软件测试开发干货知识&#xff01; &#x1f4cc; 公号同名&#xff0c;欢迎加入我的测试交流群&#xff0c;我们一起交流学习&#xff01; 可能…

Python基础-画图:matplotlib

Python画图主要用到matplotlib这个库。具体来说是pylab和pyplot这两个子库。这两个库可以满足基本的画图需求。 pylab神器&#xff1a;pylab.rcParams.update(params)。这个函数几乎可以调节图的一切属性&#xff0c;包括但不限于&#xff1a;坐标范围&#xff0c;axes标签字号…

ESP32 OTA

装好Arduino环境后&#xff0c;做了一个遥控小车&#xff1a; 1、uni-app 包装 nipplejs (Nipplejs by yoannmoinet)做了一个简单的摇杆&#xff0c;调用ESP32的WebServer接口&#xff0c;控制小车 2、ESP32 连上路由的WiFI&#xff0c;用WebServer开发了一个接口&#xff0c…

PG::Wpwn

nmap -Pn -p- -T4 --min-rate1000 192.168.225.123 nmap -Pn -p 22,80 -sCV 192.168.225.123 查看80端口的页面 尝试枚举路径 发现了/wordpress路径 使用wpscan扫描 wpscan --url http://192.168.225.123/wordpress/ -e ap 使用exploit-db搜索“social warfare” https:/…