31 - 买股票的最佳时机问题

news2024/11/16 17:54:29

文章目录

    • 1. 买股票的最佳时机I
    • 2. 买股票的最佳时机II
    • 3. 最佳买卖股票时机
    • 4. 买股票的最佳时机III
    • 5. 买股票的最佳时机IV

1. 买股票的最佳时机I

在这里插入图片描述
dp数组含义,本题两个状态:持有股票、不持有股票

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

如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来

  • 第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]
  • 第i天买入股票,所得现金就是买入今天的股票后所得现金即:-prices[i],那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);

如果第i天不持有股票即dp[i][1], 也可以由两个状态推出来

  • 第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
  • 第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]
    同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);

从递推公式可以看出,dp[i]只是依赖于dp[i - 1]的状态。所以我们只需要申请2*2的空间就可以啦。

[7,1,5,3,6,4]为例,dp数组状态如下:
在这里插入图片描述

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

2. 买股票的最佳时机II

在这里插入图片描述

  • 方法一:动态规划
    和上一题的唯一区别就是股票可以买卖多次,所以买入股票的时候,可能会有之前买卖的利润,所以 dp[1][0] = max(dp[0][0], dp[0][1] - prices[i]);
    以[8,9,2,5,4,7,1]为例,dp数组为
    在这里插入图片描述
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int dp[2][2];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i = 1; i < prices.size(); ++i){
            dp[1][0] = max(dp[0][0], dp[0][1] - prices[i]);
            dp[1][1] = max(dp[0][1], dp[0][0] + prices[i]);
            dp[0][0] = dp[1][0];
            dp[0][1] = dp[1][1];
        }
        return dp[1][1];
    }
};
  • 方法二:直接把价格上升的部分累加

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

3. 最佳买卖股票时机

在这里插入图片描述
本题就是在 买卖股票的最佳时机 II 的基础上加上了冷冻期,我们将状态分为三种:持有股票、不持有股票处于冷冻期、不持有股票不处于冷冻期。dp数组含义:

  • dp[i][0]:持有股票,能获得的最大收益
  • dp[i][1]:不持有股票,不在冷冻期,能获得的最大收益
  • dp[i][2]:不持有股票,在冷冻期,能获得的最大收益
    在这里插入图片描述
    递推公式:
  • 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][2])
  • dp[i][2] = dp[i-1][0] + prices[i]

以[1,2,3,0,2]为例,dp数组为:
在这里插入图片描述
dp[i]只是依赖于dp[i - 1]的状态。所以我们只需要申请2*3的空间就可以啦。

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

4. 买股票的最佳时机III

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

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

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

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

递推公式:

  • dp[i][0]:没买卖过股票,所能获得的最大收益保持为0
  • dp[i][1]:第一次处于持有股票状态的最大收益dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
  • dp[i][2]:第一次处于持有股票、又卖出状态的最大收益dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])
  • dp[i][3]:第二次处于持有股票状态的最大收益dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])
  • dp[i][4]:第二次处于持有股票、又卖出状态的最大收益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

以[8,9,3,5,1,3]为例,dp数组为
在这里插入图片描述

dp[i]只是依赖于dp[i - 1]的状态。所以我们只需要申请2*5的空间就可以啦

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

5. 买股票的最佳时机IV

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

使用二维数组 dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j]

j的状态表示为:

  • 0 表示不操作
  • 1 第一次买入
  • 2 第一次卖出
  • 3 第二次买入
  • 4 第二次卖出

除了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] = -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<vector<int>> dp(2, vector<int>(2 * k + 1, 0));
        for(int i = 1; i < 2 * k + 1; i += 2){
            dp[0][i] = -prices[0];
        }
        for(int i = 1; i < n; ++i){
            for(int j = 1; j < 2 * k + 1; ++j){
                if(j & 1) dp[1][j] = max(dp[0][j], dp[0][j - 1] - prices[i]);
                else dp[1][j] = max(dp[0][j], dp[0][j - 1] + prices[i]);
                dp[0][j] = dp[1][j];
            }
        }
        return dp[1][2 * k];
    }
};

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

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

相关文章

最时髦的AI画画,一文包教包会

最时髦的AI画画&#xff0c;一文包教包会 大概半年前&#xff0c;AI 绘画工具 Disco Diffusion 从 Text-to-Image 开发社区和设计行业&#xff0c;火到了普通用户的视野中。即便它界面简陋&#xff0c;满屏英文和代码&#xff0c;也“劝退”不了人们。因为对那些没有任何美术功…

kali php无法执行,直接下载或显示php文件内容

问题描述&#xff1a; 开启apache或nginx&#xff0c;访问php文件要么直接显示php文件内容&#xff0c;要么直接下载&#xff0c;这都是php文件无法解析的问题&#xff0c;需要nginxphp-fpm解决 1、安装NGINX 查看是否安装&#xff0c;如下图则已安装 #apt-cache policy ngi…

Linux安装MinIO及springboot项目整合使用实战(详细)

以往的项目&#xff0c;用的比较多的OSS服务是腾讯云和阿里云的存储服务&#xff0c;不过从去年到今年&#xff0c;最近的几个项目&#xff0c;普遍要使用Minio,所以我在开发服务器和测试服务器上都装上了minio 一、首先minio的安装 MInIO的安装有很多方法、单实例的、集群分…

Django学习——安装、创建项目、数据库、用户管理案例

目录 1、 安装django 1.1django是第三方模块&#xff0c;用pip install django 安装&#xff1a; 1.2 python的安装目录 &#xff1a; 2、创建项目 2.1在终端创建的步骤 执行过程 2.2使用pycharm&#xff08;企业版&#xff09;创建 django项目 2.3对比两种方式 2.4默认…

推荐5款体积小、无广告、超实用的办公软件

大家好&#xff0c;我又来啦&#xff0c;今天给大家带来的几款软件&#xff0c;共同特点都是无广告、超实用&#xff0c;大家观看完可以自行搜索下载哦。 1.网络分析工具——Wireshark Wireshark 是一款开源的网络分析工具&#xff0c;它可以让你捕获和浏览网络上的数据包&am…

《我命由我不由天》蔡志忠——笔记二

目录 经典记录 天才不是天生的 如何认识自己、如何发掘和重用自己 自己拯救自己才是唯一出路 了解自己是人生第一个智慧 科学家证实&#xff0c;成就与选择目标的年龄成反比&#xff01; “努力无用论” 经典记录 天才不是天生的 美国物理学家理查德费曼两三岁时&#x…

Ubuntu18.04 制作系统ISO镜像并物理机还原(Systemback)

简单记录使用Systemback工具打包Ubuntu系统得到iso镜像文件&#xff0c;并在物理机上进行还原&#xff08;安装&#xff09;的流程。测试结果发现&#xff0c;使用打包的iso文件安装得到的Ubuntu系统继承了我之前的Ubuntu系统&#xff0c;包括并不限于如下内容&#xff1a;Home…

公司新来个卷王,让人崩溃...

最近内卷严重&#xff0c;各种跳槽裁员&#xff0c;相信很多小伙伴也在准备今年的面试计划。 在此展示一套学习笔记 / 面试手册&#xff0c;年后跳槽的朋友可以好好刷一刷&#xff0c;还是挺有必要的&#xff0c;它几乎涵盖了所有的软件测试技术栈&#xff0c;非常珍贵&#x…

母亲节营销案例大盘点,真的有被狠狠共情住

⼀直以来&#xff0c;节⽇营销都是品牌借势和消费者建⽴情感链接的好时机。尤其是在母亲节这个温情的⽇⼦⾥&#xff0c;借助催泪、温情的⼴告歌颂母爱的无私与伟⼤来打动消费&#xff0c;也成为品牌母亲节营销的标配。 随之⽽来的&#xff0c;越来越多的品牌也⾯临困局&#x…

基于粒子群算法优化的核极限学习机(KELM)分类算法-附代码

基于粒子群算法优化的核极限学习机(KELM)分类算法 文章目录 基于粒子群算法优化的核极限学习机(KELM)分类算法1.KELM理论基础2.分类问题3.基于粒子群算法优化的KELM4.测试结果5.Matlab代码 摘要&#xff1a;本文利用粒子群算法对核极限学习机(KELM)进行优化&#xff0c;并用于分…

三硬币模型——机器学习课后作业

题目要求&#xff1a; 给出解决代码如下&#xff1a; import numpy as npdef miu_calc(pii, pi, qi, yj):up_b pii * pi ** yj * (1 - pi) ** (1 - yj)up_c (1 - pii) * qi ** yj * (1 - qi) ** (1 - yj)return up_b / (up_b up_c)yj np.array([1, 1, 0, 1, 0, 0, 1, 0, 1…

MySQL数据库的备份与恢复

一、数据备份的重要性 备份的主要目的是灾难恢复。 在生产环境中&#xff0c;数据的安全性至关重要。 任何数据的丢失都可能产生严重的后果。 造成数据丢失的原因&#xff1a; 程序错误人为操作错误运算错误磁盘故障灾难&#xff08;如火灾、地震&#xff09;和盗窃 二、数据…

华为OD机试 - 第一个错误的版本(Java)

一、题目描述 你是产品经理&#xff0c;目前正在带领一个团队开发新的产品。不幸的是&#xff0c;你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的&#xff0c;所以错误的版本之后的所有版本都是错的。 假设你有 n 个版本 [1, 2, …, n]&#xff…

【seata的部署和集成】

seata的部署和集成 seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、微服务集成seata1.引入依赖2.修改配置文件 三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取…

应用在虚机和容器场景下如何优雅上下线

在生产场景中部署的服务提供者常因业务升级或其他场景需要下线和上线的部署操作&#xff0c;本文总结了应用在上下线过程中会遇到的典型问题&#xff0c;并思考在虚机和容器场景该如何处理这些问题&#xff0c;规避该过程中可能出现的服务消费者的请求失败&#xff0c;实现应用…

人工智能学习07--pytorch16--MobileNet网络详解

MobileNet详解 DW卷积&#xff1a; 每个卷积核的深度为1&#xff0c;而不是像之前一样等于特征矩阵的深度。 每个卷积核只负责输入特征矩阵的一个channel进行卷积运算&#xff0c;再得到相应的输出矩阵的一个channel。 因为每个卷积核只负责一个channel&#xff0c;则采用的特征…

Android WebView 的 addJavascriptInterface 探究

Android WebView 的 addJavascriptInterface 探究 一、前言 Java和JS交互的方式有多种,这里探讨的方式是通过以下方式进行的交互。 webView.addJavascriptInterface(this, "JSBridge") 这篇文章是想弄明白 JavaScript 和 Java是如何实现这种方式互调的,就从源码…

C高级 day1

初始工作路径不在家目录下&#xff0c;在不切换路径的情况下&#xff0c;在家目录下创建一个subdir目录&#xff0c;在subdir这个目录下&#xff0c;创建subdir1和subdir2&#xff0c;并且把/etc/passwd拷贝到subdir1中&#xff0c;把/etc/group文件拷贝到subdir2中&#xff0c…

java获取登陆用户ip方法

今天和大家分享一下获取登录用户 ip的方法&#xff0c;如果你想获取自己的登陆用户 ip&#xff0c;可以参考以下思路&#xff1a; 1.可以通过 Java动态链接库的方式获取到&#xff0c;方法很简单&#xff0c;就是把需要的 ip地址添加到动态链接库中&#xff0c;然后在需要用到时…

Word三线表创建

三线表是论文写作中经常使用到的表格格式 自定义三线表 “插入”-->“表格”&#xff0c;随便插入一个表格&#xff0c;然后将光标移动到表格内 “表设计”-->“其他”-->“新建表格样式” 修改模板名称为“三线表”&#xff0c;方便下次直接套用 首先设置标题行【…