【dp】买卖股票的最佳时机系列题目

news2025/1/18 6:43:16

文章目录

    • 121. 买卖股票的最佳时机
    • 122. 买卖股票的最佳时机 II
    • 309. 最佳买卖股票时机含冷冻期
    • 123. 买卖股票的最佳时机 III
    • 188. 买卖股票的最佳时机 IV

121. 买卖股票的最佳时机

在这里插入图片描述
本题的重点是:只能在前面某一天买入,后面某一天卖出。要不就是不买入,收益为0

dp数组含义

本题两个状态:持有股票、不持有股票

  • dp[i][1] :表示第i天持有股票所得最多现金
  • dp[i][0] :表示第i天不持有股票所得最多现金

最后返回dp[n-1][0],表示最后一天不持有股票,所获得最多的现金

递推公式

第i天不持有股票所得最多现金 = max(第i-1天不持有股票手上的现金, 第i-1天手上持有股票、但是在第i天卖出手上的现金)

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

第i天持有股票手上的现金 = max(第i-1天持有股票手上的现金, 第i-1天手上没有股票、但是在第i天买入股票手上的现金)

dp[i][1] = max(dp[i-1][1], 0 - prices[i])    // i-1天不持有,第i天持有,那一定是第i天买入

初始化

  • dp[0][0]:第0天不持有股票,所能获得的现金,就是0
  • dp[0][1]:第0天持有股票,所能获得的现金,就是第0天买入股票后手上的钱,即 -prices[0]
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        // dp[i][1] 表示第i天持有股票所得最多现金
        // dp[i][0] 表示第i天不持有股票所得最多现金
        vector<vector<int>> dp(n, vector<int>(2, 0));
        dp[0][1] = 0 - prices[0];    // 第0天持有股票,手上的钱就是买入后的负数
        dp[0][0] = 0;                // 第0天不持有股票,手上的钱是0    
        for(int i = 1; i < n; i++){
            // 第i天不持有股票所得最多现金 = max(第i-1天没有股票手上的现金,  第i-1天手上持有股票、但是在第i天卖出手上的现金)
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);
            // 第i天持有股票手上的现金 = max(第i-1天持有股票手上的现金,  第i-1天手上没有股票、但是在第i天买入股票手上的现金)
            dp[i][1] = max(dp[i-1][1], 0 - prices[i]);           
        }
        return dp[n-1][0];
    }
};

第二种dp方法

第i天的最大收益 = max(第i-1天的最大收益,第i天的价格 - 前i-1天的最低价)

dp[i] = max(dp[i-1], prices[i] - min_val)
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<int> dp(n, 0);   // dp[i]:第i天的最大收益
        dp[0] = 0;
        int min_val = prices[0];
        for(int i = 1; i < n; i++){
            min_val = min(min_val, prices[i]);
            dp[i] = max(dp[i-1], prices[i] - min_val);
        }
        return dp[n-1];
    }
};

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

在这里插入图片描述

本题的重点是:可以在任意一天进行买入或卖出,且不限制买入和卖出的次数

dp数组含义

本题两个状态:持有股票、不持有股票

  • dp[i][1] :表示第i天持有股票所得最多现金
  • dp[i][0] :表示第i天不持有股票所得最多现金

最后返回dp[n-1][0],表示最后一天不持有股票,所获得最多的现金

递推公式

第i天不持有股票所得最多现金 = max(第i-1天不持有股票手上的现金, 第i-1天手上持有股票、但是在第i天卖出手上的现金)

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

第i天持有股票手上的现金 = max(第i-1天持有股票手上的现金, 第i-1天手上没有股票、但是在第i天买入股票手上的现金)

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

初始化

  • dp[0][0]:第0天不持有股票,所能获得的现金,就是0
  • dp[0][1]:第0天持有股票,所能获得的现金,就是第0天买入股票后手上的钱,即 -prices[0]
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        // dp[i][1] 表示第i天持有股票手上最多的现金
        // dp[i][0] 表示第i天不持有股票所得最多现金
        vector<vector<int>> dp(n, vector<int>(2, 0));
        dp[0][1] = 0 - prices[0];
        dp[0][0] = 0;
        // dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
        // dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])
        for(int i = 1; i < n; i++){
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]);
        }
        return dp[n-1][0];
    }
};

直接把价格上升的部分累加即可
在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int ans = 0;
        for(int i = 1; i < n; i++){
            if(prices[i] > prices[i-1]) ans += prices[i] - prices[i-1];
        }
        return ans;
    }
};

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

在这里插入图片描述

本题就是在122. 买卖股票的最佳时机 II的基础上加上了冷冻期

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

而本题中,我们将状态分为三种:持有股票、不持有股票处于冷冻期、不持有股票不处于冷冻期

dp数组含义

  • dp[i][0]:不持有股票,不在冷冻期,能获得的最大收益
  • dp[i][1]:不持有股票,在冷冻期,能获得的最大收益
  • dp[i][2]:持有股票,能获得的最大收益

在这里插入图片描述

递推公式

第i天不持有股票,且不在冷冻期能获得的最大收益 = max(前一天处于冷冻期的收益,前一天不持有股票且不在冷冻期的收益)

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

第i天不持有股票,且在冷冻期能获得的最大收益 = 前一天持有股票卖出的收益

dp[i][1] = dp[i-1][2] + prices[i]

第i天持有股票能获得的最大收益 = max(前一天持有股票没卖,前一天不持有股票且不在冷冻期但是买入股票)

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

初始化

  • dp[0][0] = 0:不持有股票,不在冷冻期
  • dp[0][1] = 0:不持有股票,在冷冻期
  • dp[0][2] = 0 - prices[0]:持有股票,第0天买入即可
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(3, 0));
        dp[0][0] = 0;  // 不持有股票,不在冷冻期
        dp[0][1] = 0;  // 不持有股票,在冷冻期
        dp[0][2] = 0 - prices[0];  // 持有股票
        
        for(int i = 1; i < n; i++){
            dp[i][0] = max(dp[i-1][1], dp[i-1][0]);
            dp[i][1] = dp[i-1][2] + prices[i];
            dp[i][2] = max(dp[i-1][2], dp[i-1][0] - prices[i]);
        }
        return max(dp[n-1][0], dp[n-1][1]);
    }
};

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

在这里插入图片描述
一天一共就有五个状态:

  • 未操作过
  • 处于第一次持有股票的状态
  • 处于第一次持有股票、又卖出的状态
  • 处于第二次持有股票的状态
  • 处于第二次不持有股票、又卖出的状态

dp数组含义

dp[i][j]:表示第i天,处于状态j时,所能获得的最大收益

  • dp[i][0]:没买卖过股票,所能获得的最大收益
  • dp[i][1]:处于第一次持有股票的状态,所能获得的最大收益
  • dp[i][2]:处于第一次持有股票、又卖出的状态,所能获得的最大收益
  • dp[i][3]:处于第二次持有股票的状态,所能获得的最大收益
  • dp[i][4]:处于第二次不持有股票、又卖出的状态,所能获得的最大收益

在这里插入图片描述

递推公式

状态0:没买卖过股票

很明显,图中没有入度,无需更新,所能获得的最大收益保持为0

状态1:第一次持有股票

第一次处于持有股票状态的最大收益 = max(前一天就处于第一次持有股票状态, 前一天没做操作、今天才买入股票)

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

状态2:第一次持有股票、又卖出

第一次处于持有股票、又卖出状态的最大收益 = max(前一天就处于第一次持有股票、又卖出状态, 前一天处于持有股票、今天才卖出)

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

状态3:第二次持有股票

第二次处于持有股票状态的最大收益 = max(前一天就处于第二次持有股票状态, 前一天处于第一次持有股票并卖出、今天才买入股票)

dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])

状态4:第二次不持有股票、又卖出

第二次处于持有股票、又卖出状态的最大收益 = max(前一天就处于第二次持有股票、又卖出状态, 前一天处于第二次持有股票、今天才卖出)

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

初始化

  • dp[0][0]:第0天没操作,收益为0
  • dp[0][1]:第0天买入,收益为-prices[0]
  • dp[0][2]:第0天买入后卖出,收益为0
  • dp[0][3]:第0天买入后卖出,再买入,收益为-prices[0]
  • dp[0][4]:第0天买入后卖出,再买入卖出,收益为0
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(5, 0));
        dp[0][1] = 0 - prices[0];
        dp[0][3] = 0 - prices[0];
        for(int i = 1; i < n; i++){
            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[n-1][4];
    }
};

观察可以发现,二维数组中,计算当前层数据时,只需要使用上方元素,以及上方相邻元素即可,和背包问题压缩维度原理一样,本题也可以压缩维度,逆序更新即可。因为计算下一行时,没有用到后面的元素,先更新后面的没有影响

其实本题不改变更新顺序也行

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

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

在这里插入图片描述

上题中,最多两笔交易时,有5个状态;本题最多k笔交易,会有2*k+1个状态,因为完成k笔交易,需要k次买入和k次卖出,再加上不做任何操作的状态,总共有2*k+1个状态

和上题一样,我们把除了0以外的奇数状态定为持有股票状态,而偶数状态定为卖出股票的状态

dp数组含义

dp[i][j]:表示第i天,处于状态j时,所能获得的最大收益,强调一下,第i天可以经过多种状态,因为不限制每天卖卖股票的次数,就像下面初始化时所描述的一样

初始化

  • dp[0][0]:第0天没操作,收益为0
  • dp[0][1]:第0天买入,收益为-prices[0]
  • dp[0][2]:第0天买入后卖出,收益为0
  • dp[0][3]:第0天买入后卖出,再买入,收益为-prices[0]
  • dp[0][4]:第0天买入后卖出,再买入卖出,收益为0

我们可以看出,奇数状态为买入状态,统一初始化为-prices[0],偶数状态为0

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

压缩维度

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

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

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

相关文章

外贸业务员怎样能提高自己的工作能力?

关于外贸业务员提高自己的工作能力&#xff0c;米贸搜整理如下&#xff0c;希望可以帮助到你&#xff1a;1.树立一个好的目标&#xff0c;并坚定不移地朝着这个目标努力。这个问题&#xff0c;无论你是新手还是有经验的外贸业务员&#xff0c;相信每个外贸业务员都或多或少的思…

K_A11_004 基于STM32等单片机采集热敏传感参数串口与OLED0.96双显示

K_A11_004 基于STM32等单片机采集热敏传感参数串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:四、部分代码说明1、接线说明1.1、STC89C52RC热敏传感模块1.2、STM32F103C8T6热敏传感模块五、基础知识学习与相关资料下…

NCS8823替代方案|CS5260Typec转VGA可替代NCS8823|低BOM成本替代NCS8823设计

NCS8823替代方案|CS5260Typec转VGA可替代NCS8823|低BOM成本替代NCS8823设计 NCS8823是一款低功耗、DisplayPort信号至VGA转换器,通过USB Type-C连接器。它是 适用于USB Type-C至VGA转换器&#xff0c;适配器、对接设备。此设备结合了基于USB Type-C的 DisplayPort接收器和VGA…

华为私有云平台FusionCompute搭建

一、FusionCompute架构 架构CNA作为虚拟化操作系统&#xff0c;VRM作为虚拟化管理平台正常主机都安装CNA&#xff0c;单独建立VRM集群作为管理集群&#xff0c;我测试环境就一台主机&#xff0c;所以CNA和VRM装在同一台主机上&#xff0c;并且用这台主机分配虚拟机进行测试。 …

前端基础(十二)_函数高级、全局变量和局部变量、 预解析(变量提升)、函数返回值

作用域 作用域指&#xff1a;变量或函数的有效使用范围&#xff0c;有全局作用域与局部作用域两种。 全局变量和局部变量 全局变量&#xff1a;直接在 script 标签下声明的变量&#xff0c;任何地方都能访问&#xff0c;任何地方都能对其值进行改变。 局部变量&#xff1a;函…

CAN总线的个人理解

部分内容可以参考&#xff1a;https://blog.csdn.net/xwwwj/article/details/105372234? CAN概念简介 CAN是Controller Area Network 的缩写 CAN协议经过ISO标准化后有两个标准&#xff1a;ISO11898标准和ISO11519-2标准。其中ISO11898是针对通信速率为125Kbps~1Mbps的高速通…

适合制造业的ERP推荐?使用ERP系统的好处有哪些?

对于制造型企业来说&#xff0c;除了涉及到产品的生产制造和原料采购&#xff0c;还需要管理库存、销售、财务等方方面面。制造业的ERP系统的使用&#xff0c;尤为重要。一个好的制造业的ERP系统在企业管理中起到至关重要的作用&#xff0c;针对制造业的ERP系统提供贴合行业特性…

用cmd命令窗口运行第一个java程序同时分享idea写的代码用cmd编译运行【建议收藏】

在上一篇文章https://blog.csdn.net/qq_52545155/article/details/128651296?spm1001.2014.3001.5502教大家安装了jdk版本&#xff0c;那么我们来编写一个java程序&#xff0c;通过cmd命令运行起来看看效果叭&#xff01;&#xff01;&#xff01; 一、基本代码准备 1、打开记…

超全的SQL注入姿势总结

目录 常见姿势 环境搭建 信息收集 报错注入 延时注入 布尔注入 堆叠注入 绕过方法 绕过引号 or and xor not绕过 绕过注释符 内联注释绕过 类型转换绕过 绕过 WAF绕过-应用层 常见姿势 环境搭建 use mysql; create table if not exists my_table( id int PRIMA…

HC小区管理系统安装记录一次群里小伙伴梓豪方式安装问题

记录一次群里小伙伴安装&#xff0c;供大家参考 问题排查 打开梓豪地址查看 Redis MySQL Nginx 是否启动成功&#xff0c;查看日志启动成功 MySQL正常 redis 没有报错 Nginx也正常 查看hc 是否启动成功&#xff0c;点击控制台 查看docker 发现8008 端口被占用了&#xff0c…

【异常】原来提示SocketTimeoutException:connect timed out还可能是外部因素导致

一、现象截图 一大早收到ELK的邮件提醒&#xff0c;让我来看看&#xff0c;又是哪个妖怪在作孽&#xff1f; 二、问题定位 2.1 SocketTimeoutException:connect timed out 经验告诉我&#xff0c;这个问题一般是第三方平台的问题&#xff0c;大部分原因是发起Http请求&…

惠普M329打印机更换副厂硒鼓后提示墨粉不足并无法打印

买了一个惠普M329打印机,打印效果不错,速度快,大量复印比较方便。因为最近打印和复印比较多,很快原装墨粉用完了。又买了一个副厂(带芯片)的硒鼓换上。不到一个月,又用光了,这次买了同一个副厂的硒鼓(不带芯片)。将原来的芯片(副厂的)拆下来,装在新硒鼓上。装到M3…

喜讯!华秋电子荣获千峰奖“2022年度产业互联网百强”,持续为电子产业增效降本!

12月28日&#xff0c;2022全球数字贸易大会专题活动“跨境产业互联网峰会暨2022年度千峰之夜”在武汉隆重举行&#xff0c;大会聚集了全国产业互联网、跨境电商平台、数字经济、资本市场等嘉宾&#xff0c;共同探讨产业互联网公司出海的机会和路径。 亿邦动力董事长郑敏介绍&am…

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 (三)奇偶校验

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 &#xff08;三&#xff09;奇偶校验 &#x1f508;声明&#xff1a; &#x1f603;博主主页&#xff1a;王_嘻嘻的CSDN博客 &#x1f9e8;未经作者允许&#xff0c;禁止转载 &#x1f511;系列专栏&#xff1a;牛客Verilog习…

房产管理系统平台架构安全需求分析

数图互通高校房产管理系统是基于公司自主研发的FMCenterV5.0平台&#xff0c;是针对中国高校房产的管理特点和管理要求&#xff0c;研发的一套标准产品&#xff1b;通过在中国100多所高校的成功实施和迭代&#xff0c;形成了一套成熟、完善、全生命周期的房屋资源管理解决方案。…

JavaAccessBridge(Java访问桥)详细介绍

Java Access Bridge 通过 Java 访问桥 API&#xff0c;您可以给使用Java应用程序编写的在windows系统上运行的图形化系统开发辅助技术应用程序。它包含本机方法&#xff0c;使您能够查看和操作有关 Java 应用程序中 GUI 元素的信息&#xff0c;这些信息将通过 Java 访问桥转发…

二维数组中各个三角形的关系,三角形的打印同理

给你一个n*n矩阵&#xff0c;按照顺序填入1到n*n的数&#xff0c;例如n5&#xff0c;该矩阵如下 (这是一个题目&#xff0c;但是我这个写法在牛客刷题中是不能正确的得分的&#xff0c;但是我找到了各个关系&#xff0c;然后分享给大家) 然后再对其进行求和处理&#xff0c;是…

在IntelliJ IDEA中使用.ignore插件忽略Git不必要提交的文件

第一步&#xff1a; 点击File->Settings&#xff0c;在左侧菜单找到Plugins&#xff0c;点击搜索栏搜索.ignore&#xff0c;点击Install 第二步&#xff1a; 重启idea -->在项目上右键->New ->.ignore file ->.gitignore file(Git) 第三部&#xff1a; 在项目中…

http协议的简单总结

目录 1.http协议的特性 2.http协议的请求 3.get请求和post请求的区别 4.http协议的响应 1.http协议的特性 http协议是建立在TCP/IP协议之上应用层协议&#xff0c;默认端口为80,8080 http协议的的特点是无状态&#xff0c;无连接&#xff08;短连接&#xff09; 2.http协…

【面试题】京东面试查漏补缺

目录一&#xff1a;笔试题1.如何获取URL中的参数方法一方法二2.怎么平铺多维数组方法一方法二&#xff1a;递归方法三&#xff1a; flat() 和 flatMap()二&#xff1a;面试题1.promise相关问题2.vue nextTick的作用和原理3.http状态码304缓存相关问题4.其他常规问题省略wh零售事…