代码随想录算法训练营DAY48|C++动态规划Part9|121.买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III

文章目录

  • 121.买卖股票的最佳时机
    • 思路
    • CPP代码
  • 122.买卖股票的最佳时机II
    • 思路
    • CPP代码
  • 123.买卖股票的最佳时机III
    • 思路
    • CPP代码

121.买卖股票的最佳时机

力扣题目链接

文章讲解:121.买卖股票的最佳时机

视频讲解:动态规划之 LeetCode:121.买卖股票的最佳时机1

状态:非常与众不同的动态规划题,也是一类典型的动态规划题。

思路

  • dp数组的含义

dp[i][0]表示第i天持有这支股票能获得的最大现金,dp[i][1]表示第i天不持有这支股票能获得的最大现金。

最终要求的结果就是最后一天的状态:max(dp[len-1][0], dp[len-1][i])

并且应该注意的是,我们这里是第i天持有这支股票,并不代表我在第i天才买,我有可能之前就买了;同理,我们第i天不持有这支股票并不代表我第i天才卖。并且我们在最后拿结果的时候,肯定是dp[len(prices)][1],因为无论怎么着,我们不持有这支股票获利肯定都比在最后一天还持有股票来的高

  • 递推公式

    • 先讨论一下dp[i][0]

      • 首先确定do[i][0]表示第i天持有这支股票,那么dp[i-1][0]呢?其实他们两个是相等的, 因为我们前后两天都是持有股票;

        再一个,我们我们是在第i天才买入这支股票的话,那么也就是说我在i-1天是不持有这支股票的,并且在第i天花了买股票的钱所以直接dp[i][0]直接就是-price[i]

        综上所述:dp[i][0]=max(dp[i-1][0], -prices[i])

    • 再就是dp[i][1]

      • 同理,我们的前一天也可以是不持有这支股票的状态dp[i-1][1],此时的话和dp[i][1]他们两个相等
      • 那么如果,我们在第i天把这支股票给卖了变成了dp[i][1],那么此时我们现在手里的钱就是前一天持有股票的最大金额再加上今天卖股票赚的钱dp[i-1][0]+prices[i]
      • 综上所述:dp[i][1]=max(dp[i-1][1], dp[i-1][0]+prices[i])
  • dp数组的初始化

从公式可以看出来,我们的dp[0][0]dp[0][1]是我们整个递推公式的基础,那么dp[0][0]=-prices[0]dp[0][1]=0;然后其他的均初始化为多少其实都无所谓。

  • 遍历顺序

没讲究,直接从前向后遍历

  • 举例推导dp数组

以示例1,输入:[7,1,5,3,6,4]为例,dp数组状态如下:

20210224225642465

CPP代码

我们从递推公式可以看出:

dp[i][0] = max(dp[i - 1][0], -prices[i]);
dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);

dp[i]只与dp[i-1]的状态有关,所以完全可以用滚动数组,也就是只需要记录 当前天的dp状态和前一天的dp状态就可以了

class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<vector<int>> dp(2, vector<int>(2)); // 注意这里只开辟了一个2 * 2大小的二维数组dp[0][0] -= prices[0];dp[0][1] = 0;for (int i = 1; i < len; i++) {dp[i % 2][0] = max(dp[(i - 1) % 2][0], -prices[i]);dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);}return dp[(len - 1) % 2][1];}
};

122.买卖股票的最佳时机II

力扣题目链接

文章链接:122.买卖股票的最佳时机II

视频链接:动态规划,股票问题第二弹 | LeetCode:122.买卖股票的最佳时机II

状态:可以实现多次买卖,这个时候最主要的不同体现在递推公式上。如果会121.买卖股票的最佳时机,本题就比较简单

思路

本题唯一的区别就是本题的股票可以买卖多次(只有一只股票,所以再次购买前要出售掉之前的股票)

所以本题和121.买卖股票的最佳时机唯一的区别就在于递推公式,其他的地方都是一样的。首先,我们重申一下dp数组的含义:dp[i][0] 表示第i天持有股票所得现金;dp[i][1] 表示第i天不持有股票所得最多现金

  • 递推公式

在121.买卖股票的最佳时机中,由于股票全程只能买卖一次,所以如果买入股票,那么第i天持有股票即dp[i][0]一定就是 -prices[i]

本题,因为一只股票可以买卖多次,所以当第i天买入股票的时候,所持有的现金可能有之前买卖过的利润


接下来开始讨论核心代码:

那么如果第i天持有股票,如果是在第i天买入的,那么所得现金就是昨天不持有股票的现金再减去今天股票的价格,所以dp[i - 1][1] - prices[i]

如果第i天不持有股票即dp[i][1]

  1. i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
  2. i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]

综上所述:递推公式为

            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); // 注意这里是和121. 买卖股票的最佳时机唯一不同的地方。dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);

CPP代码

这里仅给出滚动数组版本的代码( 只记录当前天的dp状态和前一天的dp状态

class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<vector<int>> dp(2, vector<int>(2)); // 注意这里只开辟了一个2 * 2大小的二维数组dp[0][0] -= prices[0];dp[0][1] = 0;for (int i = 1; i < len; i++) {dp[i % 2][0] = max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] - prices[i]);dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);}return dp[(len - 1) % 2][1];}
};

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

力扣题目链接

文章链接:123.买卖股票的最佳时机III

视频链接:动态规划,股票至多买卖两次,怎么求? | LeetCode:123.买卖股票最佳时机III

状态:看到困难吓我一跳

本题有又变套路了,题目中谈到,至多买卖两次,这就意味着可以买卖一次、可以买卖两次、也可以不买卖。

但其实最本质的无非就是要设置的状态多多了,之前我们也就两个状态,持有和不持有

思路

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

现在,我们状态比之前多多了:

  1. 没有操作 (其实我们也可以不设置这个状态)
  2. 第一次持有股票
  3. 第一次不持有股票
  4. 第二次持有股票
  5. 第二次不持有股票

dp[i][j]i表示第i天,j[0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。

  • 确定递推公式
  1. 我们确定dp[i][1]的状态
    在这里插入图片描述

我们应该从两种情况里选择最大的,即dp[i][1]=max(dp[i-1][0]=prices[i], dp[i-1][1])

  1. 确定dp[i][2]的状态

在这里插入图片描述

同理dp[i][2]=max(dp[i-1][1] + prices[i], do[i-1][2])

3.确定dp[i][3]的状态

在这里插入图片描述

同理dp[i][3]=max(dp[i-1][2] + prices[i], do[i-1][3])

  1. 确定dp[i][4]的状态

在这里插入图片描述

同理dp[i][4]=max(dp[i-1][3] + prices[i], do[i-1][4])

  • dp数组的初始化

首先,我们只用初始化第0天,因为从此之后的n天都是由前一天初始化来的。

然后,dp[0][0]显然是等于0的,

每次的买入操作应当初始化为-prices[0],因为买入我们本次的钱肯定就是负数了,至于第二次买入可以理解为我们第零天先买入,再卖出,然后再买入

卖出操作应该初始化为0,因为就算再同一天买入卖出收获的钱肯定是0

vector<vector<int>> dp(prices.size(), vector<int>(5, 0));
dp[0][1] = -prices[0];
dp[0][3] = -prices[0];
  • 确定遍历顺序

跟之前的一样,从左到右即可

  • 举例推导dp数组

以输入[1,2,3,4,5]为例

20201228181724295-20230310134201291

我们最终的最大利润肯定是出现在最后一天的第二次dp[4][4]

CPP代码

class Solution {
public:int maxProfit(vector<int>& prices) {if (prices.size() == 0) return 0;vector<vector<int>> dp(prices.size(), vector<int>(5, 0));dp[0][1] = -prices[0];dp[0][3] = -prices[0];for (int i = 1; i < prices.size(); i++) {dp[i][0] = dp[i - 1][0];dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i]);dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]);}return dp[prices.size() - 1][4];}
};//空间优化(滚动数组)
class Solution {
public:int maxProfit(vector<int>& prices) {if (prices.size() == 0) return 0;vector<int> dp(5, 0);dp[1] = -prices[0];dp[3] = -prices[0];for (int i = 1; i < prices.size(); i++) {dp[1] = max(dp[1], dp[0] - prices[i]);dp[2] = max(dp[2], dp[1] + prices[i]);dp[3] = max(dp[3], dp[2] - prices[i]);dp[4] = max(dp[4], dp[3] + prices[i]);}return dp[4];}
};

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

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

相关文章

【Mac】Lightroom Classic 2024 v13.1安装教程

软件介绍 Lightroom Classic 2024是Adobe公司推出的一款专业的数字图像处理软件&#xff0c;旨在为摄影师提供强大的工具和功能&#xff0c;以管理、编辑和分享他们的照片作品。以下是Lightroom Classic 2024的主要特点和功能&#xff1a; 数字照片管理&#xff1a; 提供直观…

如何在postman上提交文件格式的数据

如何在postman上提交文件格式的数据 今天在写一个文件上传的功能接口时&#xff0c;想用postman进行提交&#xff0c;花了些时间才找到在postman提交文件格式的数据。记录一下吧&#xff01; 1.打开postman&#xff0c;选择POST提交方式&#xff0c;然后在Params那一行的Head…

求职应聘找工作,如何看待企业在线人才测评

求职者面试的过程当中&#xff0c;除了要向求职的单位展现自身的业务能力之外&#xff0c;更需要展现其他方面的优势。企业人才测评对求职者存在哪些好处&#xff1f; 可能觉得参加测评只是面试的一部分&#xff0c;但是没有测评的情况下&#xff0c;求职者很有可能很难真正全…

【C++题解】1300. 小明暑假的零花钱

问题&#xff1a;1300. 小明暑假的零花钱 类型&#xff1a;多分支结构 题目描述&#xff1a; 小明同学的妈妈在期末考试之后决定根据小明的考试成绩奖励小明不同的暑假零花钱&#xff0c;如果考试成绩在90 分以上&#xff08;包括 90 分&#xff09;&#xff0c;零花钱是成绩…

2024.5.2

List容器实现 #include <iostream> #include <list> using namespace std;int main() {list<int> l1;l1.assign(1,13);cout << *l1.begin() << endl;cout <<l1.front() << endl;l1.assign(2,78);l1.insert(l1.end(),100);l1.push_b…

导数之光:探寻机器学习中的微变奥秘

在当今这个数据驱动的时代&#xff0c;机器学习以其强大的学习和预测能力&#xff0c;成为了推动科技进步的重要力量。而在机器学习的背后&#xff0c;数学原理&#xff0c;尤其是导数的应用&#xff0c;为其提供了坚实的理论支撑。本文将详细探讨导数在机器学习中的体现&#…

人工智能|推荐系统——工业界的推荐系统之概要

以小红书为例的推荐系统的转化流程&#xff0c;用户看到内容就是曝光&#xff0c;可以点击进去&#xff0c;然后进行一些“交互”行为&#xff0c;比如评论、点赞、收藏、转发。 通常会考虑用户的一些消费指标 而从推荐系统的角度则会考虑一些北极星指标&#xff0c;也就是优化…

CMake:嵌套的CMake与多级项目管理(八)

1、嵌套的CMake 如果项目很大或者项目中有很多的源码目录&#xff0c;在通过CMake管理项目的时候如果只使用一个CMakeLists.txt&#xff0c;那么这个文件会相对比较复杂&#xff0c;有一种化繁为简的方式就是给每个源代码目录都添加一个CMakeLists.txt文件&#xff08;头文件不…

Debian操作系统的常用指令介绍

Debian是一个流行的Linux操作系统&#xff0c;以其稳定性和安全性而闻名。对于Debian用户来说&#xff0c;掌握一些基本的命令行指令是非常重要的&#xff0c;因为它们可以帮助你更高效地管理系统。在这篇博客中&#xff0c;我们将介绍一些在Debian系统中常用的指令及其功能。 …

远程桌面报错:【出现验证错误。要求的函数不受支持】

WinR 输入【gpedit.msc】回车 依次打开 计算机配置----管理模板-----系统-----凭据分配---加密数据库修正 选择【已启用】&#xff0c;下拉菜单选择【易受攻击】

24.5.2数据结构|顺序表实现

主要是记笔记&#xff0c;留着以后复习回来看的&#xff0c;有些内容解释的并不清晰。也就稍微可以借鉴借鉴。 一、如何定义结构&#xff1f; 应该有的部分用来约束的部分 二、看书搞清楚顺序表实现流程 1、准备工作&#xff1a;如何定义结构体&#xff1f;SeqList&#xf…

每日一题(力扣213):打家劫舍2--dp+分治

与打家劫舍1不同的是它最后一个和第一个会相邻&#xff0c;事实上&#xff0c;从结果思考&#xff0c;最后只会有三种&#xff1a;1 第一家不被抢 最后一家被抢 2 第一家被抢 最后一家不被抢 3 第一和最后一家都不被抢 。那么&#xff0c;根据打家劫舍1中的算法 我们能算出在i…

【Java笔记】第5章:函数

前言1. 函数的理解2. 函数的基本使用3. 函数的参数4. 函数的返回值5. 函数的执行机制6. 函数的递归调用结语 ↓ 上期回顾: 【Java笔记】第4章&#xff1a;深入学习循环结构 个人主页&#xff1a;C_GUIQU 归属专栏&#xff1a;【Java学习】 ↑ 前言 各位小伙伴大家好&#xff…

java递归-(迷宫问题)

前面 这里我们来玩个有趣的事情&#xff0c;链接是0221_韩顺平Java_老鼠出迷宫1_哔哩哔哩_bilibili 我们要找的是小老鼠按路径走到右下点 要点 我们这里方法调用时对于引用类型&#xff1a;如java中引用数据类型有哪些&#xff1f;_java引用数据类型-CSDN博客 会共享引用类型…

浏览器安装路径位置的查看、指定网址快捷方式的创建

浏览器安装路径位置的查看、指定网址快捷方式的创建 浏览器安装路径位置的查看 法一、属性查看法 右键点击浏览器的桌面图标&#xff0c;选择“属性”&#xff0c;“快捷方式”页中的“目标”框中可见. 以Microsoft Edge浏览器为例&#xff0c;参见下图&#xff1a; 法二、地…

电商核心技术揭秘四十三:电商平台营销策略浅析(下)

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商技术揭秘四十一&#xff1a;电商平台的营销系统浅析 电商技术揭秘四十二&#…

CTF-WEB(MISC)

安全攻防知识——CTF之MISC - 知乎 CTF之MISC杂项从入门到放弃_ctf杂项 你的名字-CSDN博客 CTF MICS笔记总结_archpr 掩码攻击-CSDN博客 一、图片隐写 CTF杂项---文件类型识别、分离、合并、隐写_ctf图片分离-CSDN博客 EXIF&#xff08;Exchangeable Image File&#xff09;是…

Nacos单机模式集成MySQL

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Nacos支持三种部署…

Uniapp好看登录注册页面

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

富文本编辑器CKEditor4简单使用-08(段落首行缩进插件 + 处理粘贴 Microsoft Word 中的内容后保持原始内容格式(包括首行缩进))

富文本编辑器CKEditor4简单使用-08&#xff08;段落首行缩进插件 处理粘贴 Microsoft Word 中的内容后保持原始内容格式&#xff08;包括首行缩进&#xff09;&#xff09; 1. 缩进&#xff0c;特殊方式处理——修改原工具栏里的增加缩进量2 缩进&#xff0c;插件处理——不含…