LeetCode刷题复盘笔记—一文搞懂动态规划之188. 买卖股票的最佳时机 IV问题(动态规划系列第二十三篇)

news2024/11/25 7:01:10

今日主要总结一下动态规划的一道题目,188. 买卖股票的最佳时机 IV

题目:188. 买卖股票的最佳时机 IV

Leetcode题目地址
题目描述:
给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

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

示例 1:

输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

示例 2:

输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。

提示:

0 <= k <= 100
0 <= prices.length <= 1000
0 <= prices[i] <= 1000

本题重难点

这道题目可以说是动态规划:一文搞懂动态规划之123. 买卖股票的最佳时机 III问题的进阶版,这里要求至多有k次交易。

动规五部曲,分析如下:

  1. 确定dp数组以及下标的含义
    在一文搞懂动态规划之123. 买卖股票的最佳时机 III问题中,我是定义了一个二维dp数组,本题其实依然可以用一个二维dp数组。
    使用二维数组 dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j]
    j的状态表示为:
    0 表示不操作
    1 第一次买入
    2 第一次卖出
    3 第二次买入
    4 第二次卖出

    大家应该发现规律了吧 ,除了0以外,偶数就是卖出,奇数就是买入。
    题目要求是至多有K笔交易,那么j的范围就定义为 2 * k + 1 就可以了。
    所以二维dp数组的C++定义为:
    vector<vector> dp(prices.size(), vector(2 * k + 1, 0));

  2. 确定递推公式
    还要强调一下:dp[i][1],表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是很多同学容易陷入的误区。
    达到dp[i][1]状态,有两个具体操作:
    操作一:第i天买入股票了,那么dp[i][1] = dp[i - 1][0] - prices[i]
    操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]
    选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
    同理dp[i][2]也有两个操作:
    操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
    操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]
    所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])
    同理可以类比剩下的状态,代码如下:

for (int j = 0; j < 2 * k - 1; j += 2) {
    dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);
    dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);
}

本题和一文搞懂动态规划之123. 买卖股票的最佳时机 III问题最大的区别就是这里要类比j为奇数是买,偶数是卖的状态。

  1. dp数组如何初始化
    第0天没有操作,这个最容易想到,就是0,即:dp[0][0] = 0;
    第0天做第一次买入的操作,dp[0][1] = -prices[0];
    第0天做第一次卖出的操作,这个初始值应该是多少呢?
    首先卖出的操作一定是收获利润,整个股票买卖最差情况也就是没有盈利即全程无操作现金为0,
    从递推公式中可以看出每次是取最大值,那么既然是收获利润如果比0还小了就没有必要收获这个利润了。
    所以dp[0][2] = 0;
    第0天第二次买入操作,初始值应该是多少呢?
    不用管第几次,现在手头上没有现金,只要买入,现金就做相应的减少。
    第二次买入操作,初始化为:dp[0][3] = -prices[0];
    所以同理可以推出dp[0][j]当j为奇数的时候都初始化为 -prices[0]
    代码如下:
for (int j = 1; j < 2 * k; j += 2) {
    dp[0][j] = -prices[0];
}

在初始化的地方同样要类比j为偶数是卖、奇数是买的状态。

  1. 确定遍历顺序
    从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。

  2. 举例推导dp数组

以输入[1,2,3,4,5],k=2为例。
在这里插入图片描述
最后一次卖出,一定是利润最大的,dp[prices.size() - 1][2 * k]即红色部分就是最后求解。

C++代码

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

当然有的解法是定义一个三维数组dp[i][j][k],第i天,第j次买卖,k表示买还是卖的状态,从定义上来讲是比较直观。

但三维数组操作起来有些麻烦,直接用二维数组来模拟三维数组的情况代码看起来会清爽一些。


总结

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

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

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

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

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

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

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

相关文章

带有匹配滤波器的雷达信号调制和脉冲压缩Matlab仿真

up目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 匹配滤波器&#xff1a; 匹配滤波器是输出端的信号瞬时功率与噪声平均功率的比值最大的线性滤波器也就是说有最大的信噪比。其滤波器的传递函数形式是信号频谱的共轭。在通信系统中&#xff0c;滤波器是其中重…

Selenium3自动化测试【40】Html测试报告

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

Aspartic acid-PEG-BSA 天冬氨酸-聚乙二醇-牛血清白蛋白

产品名称&#xff1a;天冬氨酸-聚乙二醇-牛血清白蛋白 英文名称&#xff1a;Aspartic acid-PEG-BSA 纯度&#xff1a;95% 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 外观:固体或粘性液体&#xff0c;取决于分子量 PEG分子量可选&#xff1a;350、550、750、1k…

Android Kotlin使用APT手写ButterKnife

前言 ButterKnife通过使用BindView注解就可以完成findViewById工作&#xff0c;它的实现原理其实也很简单&#xff0c;通过APT&#xff08;Annotation Processing Too,注解解析器&#xff09;技术&#xff0c;在编译期为我们生成了一个绑定类&#xff0c;而从完成了View的绑定…

OpenAI掌门人Sam Altman:AI的下一个发展阶段

来源&#xff5c;Greylock OneFlow社区编译 翻译&#xff5c;胡燕君、贾川 预告了一整年的GPT-4迟迟没来&#xff0c;人们猜想OpenAI是不是要跳票了&#xff0c;更何况他们之前的得意之作DALL-E也被开源Stable Diffusion打了个措手不及&#xff0c;再不来点深水炸弹业界地位危矣…

jsp+ssm计算机毕业设计ssm学生成绩考核管理系统【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

对 CSS 工程化的理解

CSS 工程化是为了解决以下问题&#xff1a; 宏观设计&#xff1a;CSS 代码如何组织、如何拆分、模块结构怎样设计&#xff1f;编码优化&#xff1a;怎样写出更好的 CSS&#xff1f;构建&#xff1a;如何处理我的 CSS&#xff0c;才能让它的打包结果最优&#xff1f;可维护性&a…

SQL基础——查询基础

查询基础前言整体思维导图列的查询语法2.1 基本的SELECT语句代码示例&#xff1a;从Product表中输出3列执行结果查询出所有的列语法2.2 查询全部的列代码示例2.2 输出Product表中全部的列执行结果为列设置别名代码示例2.3 为列设置别名执行结果代码示例2.4 设置中文别名执行结果…

Redis持久化没玩明白,你就会把缓存数据丢了

引言 我们都知道Redis是微服务架构中重要的基础数据库中间件&#xff0c;通过Redis可以将数据库中的数据缓存到内存中&#xff0c;当服务端有数据查询请求的时候&#xff0c;可以直接从内存中获取数据。如此&#xff0c;一方面服务端可以获得比较快的数据请求响应&#xff0c;…

透明质酸-嵌段共聚物 透明质酸修饰聚乳酸 HA-PLA/PCL/PLGA/PEI/PLL

品牌&#xff1a;为华生物 产地&#xff1a;广州 中文名称&#xff1a;透明质酸-聚乳酸 英文名称&#xff1a;HA-PLA 溶解度&#xff1a;溶于部分有机溶剂 保存时间&#xff1a;一年 PLA分子量&#xff1a;根据客户要求定制 HA分子量&#xff1a;3000--1500K 其他分子量可根据客…

鑫磊股份通过注册:年营收8.2亿 为钟仁志与蔡海红夫妻店

雷递网 雷建平 12月15日鑫磊压缩机股份有限公司&#xff08;简称&#xff1a;“鑫磊股份”&#xff09;日前通过注册&#xff0c;准备在深交所创业板上市。鑫磊股份计划募资4.53亿元&#xff0c;其中&#xff0c;1.97亿元用于新增年产3万台螺杆式空压机技改项目&#xff0c;1.0…

Python+Selenium使用Page Object实现页面自动化测试

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

03解锁源码分析-ReentrantReadWriteLock原理-AQS-并发编程(Java)

文章目录1 读锁解锁1.1 tryReleaseShared()1.2 doReleaseShared()1.3 unparkSuccessor()1.4 示意图2 写锁解锁2.1 tryRelease()2.2 尝试解锁成功2.3 setHeadAndPropagate()5 后记1 读锁解锁 查看下读锁的解锁相关源代码&#xff1a; public void unlock() {sync.releaseShare…

【实时数仓】在Hbase建立维度表、保存维度数据到Hbase、保存业务数据到kafka主题

文章目录一 分流Sink之建立维度表到HBase(Phoenix)1 拼接建表语句&#xff08;1&#xff09;定义配置常量类&#xff08;2&#xff09;引入依赖&#xff08;3&#xff09;hbase-site.xml&#xff08;4&#xff09;在phoenix中执行&#xff08;5&#xff09;增加代码a TableProc…

Docker安装简单命令

一、 Docker是什么? 要了解Docker&#xff0c;首先要了解什么是容器&#xff1f; 容器是一个软件的轻量级独立可执行软件包&#xff0c;包含运行它所需的一切&#xff1a;代码&#xff0c;运行时&#xff0c;系统工具&#xff0c;系统库&#xff0c;设置。不管环境如何&…

C++(第十二篇):多态(虚函数、抽象类、虚函数表、虚表指针、多继承下的多态)

&#x1f4d2;博客主页&#xff1a;Morning_Yang丶 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4cc;本文所属专栏&#xff1a; 【C拒绝从入门到跑路】 &#x1f64f;作者水平有限&#xff0c;如果发现错误&#xff0c;敬请指正&…

13485-59-1,二肽Ala-Pro,H2N-AP-OH

Substrate for skin fibroblast prolidase.皮肤成纤维细胞prolida酶的底物。 编号: 199181中文名称: 二肽Ala-Pro英文名: Ala-ProCAS号: 13485-59-1单字母: H2N-AP-OH三字母: H2N-Ala-Pro-COOH氨基酸个数: 2分子式: C8H14N2O3平均分子量: 186.21精确分子量: 186.1等电点(PI): 6…

web前端期末大作业:红色主题中国文化网页设计与实现——基于HTML+CSS实现中国梦(20页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

电脑技巧:Win11系统新增的磁盘分区功能介绍

很多用户发现&#xff0c;新买的电脑中出厂自带的硬盘只有一个分区&#xff0c;目前只有少部分电脑机型出厂会有分多个分区的。 磁盘的单一分区往往不能满足我们的使用需要&#xff0c;Win7/8/10我们都知道可以在磁盘管理下通过压缩卷的方式来分区&#xff0c;Win11操作系统又新…

C# 程序的错误与调试

一 错误的zhongl 程序的错误通常可以分为三大类 ① 语法错误 ② 运行错误 ③ 逻辑错误 二 语法错误 1 常见的语法错误 ① 如括号不配对&#xff0c;多了或少了分号&#xff1b; ② 字母写错&#xff0c;变量未定义&#xff0c;控件命名写错&#xff1b; ③ 函数少了一个参数…