买卖股票的各种最佳时机问题

news2024/12/26 23:29:43
买卖股票的最佳时机

分析

根据题意可知,我们只需要找出来一个最小价格的股票和一个最大价格的股票,并且最小价格的股票出现在最大价格的股票之前。

如果尝试使用暴力解法,时间复杂度为O(N^2),对于题目中给的长度,显然是会超时的,因此我们需要另寻它法。

我们可以使用一次遍历,在经过每个值时,计算出包含该值之前的股票的最低价格和最大利润,该种方法的时间复杂度为O(N),显然是可解的。

初始化:由于在确定价格最小值时涉及到min求最小值,而且根据题目所给价格的范围,我们可以使用 0x3f3f3f3f 来初始化minprice;根据题意,由于利润最小为0,不涉及到为负的情况,因此初始化 profit 为0即可。

填表顺序:从左到右。

返回值:profit

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        int profit=0,minprice=0x3f3f3f3f;
        for(int price:prices){
            profit=max(profit,price-minprice);
            minprice=min(price,minprice);
        }
        return profit;
    }
};
买卖芯片的最佳时机

分析

根据题意,只需找到一个最低价格和一个最高价格,并且最低价格出现在最高价格之前,显然与上面的题意是一样的,解法显而易见也是一样的。

代码

class Solution {
public:
    int bestTiming(vector<int>& prices) {
        int n=prices.size();
        int profit=0,minprice=0x3f3f3f3f;
        for(int price:prices){
            profit=max(profit,price-minprice);
            minprice=min(price,minprice);
        }
        return profit;
    }
};
买卖股票的最佳时机II

分析

如果以以往经验,对于本题,我们可以定义一个 dp 表,dp[i] 表示以 i 位置为结尾,能获取的最大利润,即:

由于题目中涉及到该天“买股票”和“卖股票”的问题,因此,仅仅使用一维 dp 是不能解决问题的,因此可以尝试使用二维 dp 来解决,dp[i][0] 表示手里没股票的时候能获取的最大利润,dp[i][1]表示手里有股票的时候能获取的最大利润(易知这里说的有股票指的是“一张股票”)。

状态转移方程: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])

初始化:由于只会用到前一行的值,因此只需初始化第一行的值即可,dp[0][0]表示第1天手里没股票的最大利润,为0;dp[0][1]表示第一天手里有股票的最大利润,为 -prices[0]。

填表顺序:从上到下。

返回值:dp[n-1][0],因为最后一天手里有股票肯定是比最后一天没股票要亏。

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        vector<vector<int>> dp(n,vector<int>(2));
        dp[0][1]=-prices[0];
        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];
    }
};
买卖股票的最佳时机含手续费

分析

 如果以以往经验,对于本题,我们可以定义一个 dp 表,dp[i] 表示以 i 位置为结尾,能获取的最大利润,即:

由于题目涉及到该天“买股票”和“卖股票”这两种情况,显然只表示该天为结尾能获取的最大利润,是非常模糊的,那么问题也得不到解决。

因此考虑使用二维 dp 来解决问题,dp[i][0]表示第 i 天手里没股票的时候能获取的最大利润;dp[i][1]表示第 i 天手里有股票的时候能获取的最大利润(显然,根据题意,这里所说的有股票指的是“一张股票”)。

状态转移方程:dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);

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

初始化:由于只会用到前一行的值,因此只需初始化第一行的值即可,dp[0][0]表示第1天手里没股票的最大利润,为0;dp[0][1]表示第一天手里有股票的最大利润,为 -prices[0]。

填表顺序:从上到下。

返回值:dp[n-1][0],因为最后一天手里有股票肯定是比最后一天没股票要亏。

解法一

代码

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int n=prices.size();
        vector<vector<int>> dp(n,vector<int>(2));
        //dp[i][0] 表示没股票的最大利润
        //dp[i][1] 表示有股票的最大利润
        dp[0][1]=-prices[0];
        for(int i=1;i<n;i++){
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);
            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 fee) {
        int n=prices.size();
        int a=0,b=-prices[0];
        //a 表示没股票的最大利润
        //b 表示有股票的最大利润
        for(int i=1;i<n;i++){
            int a1=max(a,b+prices[i]-fee);
            int b1=max(b,a-prices[i]);
            a=a1,b=b1;
        }
        return a;
    }
};
解法三(贪心)

仔细分析前两种解法,不难发现,都是在卖出股票的时候进行决策优劣的,我们不妨尝试在买入股票的时候进行优劣的决策。

定义buy表示买入价格(含手续费),当某天价格+手续费 < buy 的时候,表示我们可以用更低成本卖股票,则更新 buy=prices[i]+fee。

定义profit表示能获取的最大利润,当prices[i] > buy的时候,我们会卖出股票,但是这里需要注意的是,如果我们这个时候卖出股票,可能不是最优的,因为可能之后的价格更高,即一张股票可以赚更高的利润,因此我们可以尝试以下策略:先卖掉,并把 buy 更新为 prices[i],那么在之后遇到更高价格之后,只需加上差价即可,即:我们是提供了一种“可以反悔”的操作。

代码

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int n=prices.size();
        int buy=prices[0]+fee;
        int profit=0;
        for(int i=1;i<n;i++){
            if(prices[i]+fee < buy)
                buy=prices[i]+fee;
            else if(prices[i] > buy){
                profit+=prices[i]-buy;
                buy=prices[i];
            }
        }
        return profit;
    }
};
买卖股票的最佳时期含冷冻期

分析

  如果以以往经验,对于本题,我们可以定义一个 dp 表,dp[i] 表示以 i 位置为结尾,能获取的最大利润,即:

由于题目涉及到该天“买股票”,“卖股票”和“冷冻期”这三种情况,显然只表示该天为结尾能获取的最大利润,是非常模糊的,那么问题也得不到解决。

因此考虑使用二维 dp 来解决问题,dp[i][0]表示第 i 天手里有股票的时候能获取的最大利润(显然,根据题意,这里所说的有股票指的是“一张股票”);dp[i][1]表示手里没股票,当天处于冷冻期的最大利润;dp[i][2]表示手里没股票,当天不处于冷冻期的时候所能获取的最大利润。

状态转移方程:dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]);

                         dp[i][1]=dp[i-1][0]+prices[i];

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

初始化:根据状态转移方程可知,每次填值只会用到上一行的值,因此只需初始化第一行即可,

              dp[0][0]= -prices[0],dp[0][1]=0,dp[0][2]=0。

填表顺序:从上到下。

返回值:max(dp[n-1][1],dp[n-1][2]).因为最后一天手里有股票肯定是比最后一天手里没股票要亏的.

解法一

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        vector<vector<int>> dp(n,vector<int>(3));
        dp[0][0]=-prices[0];
        //dp[i][0] 手里有股票的最大利润
        //dp[i][1] 手里没股票,处于冷冻期的最大利润
        //dp[i][2] 手里没股票,不处于冷冻期的最大利润
        for(int i=1;i<n;i++){
            dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]);
            dp[i][1]=dp[i-1][0]+prices[i];
            dp[i][2]=max(dp[i-1][1],dp[i-1][2]);
        }
        return max(dp[n-1][1],dp[n-1][2]);
    }
};
解法二

根据解法一可知,每次填值只会用到上一行的三个值,因此可以尝试用几个变量来解决,时间复杂度为O(N)。

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        int a=-prices[0],b=0,c=0;
        //a 手里有股票的最大利润
        //b 手里没股票,处于冷冻期的最大利润
        //c 手里没股票,不处于冷冻期的最大利润
        for(int i=1;i<n;i++){
            int a1=max(a,c-prices[i]);
            int b1=a+prices[i];
            int c1=max(b,c);
            a=a1,b=b1,c=c1;
        }
        return max(b,c);
    }
};
买卖股票的最佳时机III

分析

   如果以以往经验,对于本题,我们可以定义一个 dp 表,dp[i] 表示以 i 位置为结尾,能获取的最大利润,即:

由于该题涉及“买股票”,“卖股票”和“交易次数”的问题,显然使用一维dp是不能解决问题的。

我们可以使用三维 dp 来解决,dp[i][j][k],i 表示第 i 天,j 表示处于手里有股票还是没股票,k 表示已交易次数,这样看来,三维的有点头疼。

我们不妨可以使用两个二维dp来解决,f[i][j]表示手里没股票,已交易 j 次能获取的最大利润,g[i][j]表示手里有股票,已交易 j 次能获取的最大利润。

状态转移方程:f[i][j]=max(f[i-1][[j],g[i-1][j-1]+prices[i])【注意:使用g[i-1][j-1]须满足 j >=1】

                         g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]).

初始化:对于f[i][j]来说,会用到上一行的值,因此只需初始化第一行即可,由于第一行表示第一天,因此最多交易0次,对于高于0次的情况并不可能出现,初始化为 -0x3f3f3f3f.

              对于g[i][j]来说,会用到上一行的值,也可能用到前一行前一列的值(左上方)【因此不需要初始化】

填表顺序:从上到下,从左到右。

返回值:f[i][j]里面的最大值。

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        vector<vector<int>> f(n,vector<int>(3,-0x3f3f3f3f));
        vector<vector<int>> g(n,vector<int>(3,-0x3f3f3f3f));
        //f[i][j] 表示没股票的时候,已经交易j次,获取的最大利润
        //g[i][j] 表示有股票的时候,已经交易j次,获取的最大利润
        f[0][0]=0,g[0][0]=-prices[0];
        for(int i=1;i<n;i++){
            for(int j=0;j<=2;j++){
                f[i][j]=f[i-1][j];
                if(j>=1)
                    f[i][j]=max(f[i][j],g[i-1][j-1]+prices[i]);
                g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]);
            }
        }
        return *max_element(f[n-1].begin(),f[n-1].end());
    }
};
买卖股票的最佳时机IV

分析

这道题与上一道题相比,差异之处为上一道题限制交易次数最多为两次,本题限制交易次数最多为k次,所以解法和代码同上一道题几乎    如出一辙。

   如果以以往经验,对于本题,我们可以定义一个 dp 表,dp[i] 表示以 i 位置为结尾,能获取的最大利润,即:

由于该题涉及“买股票”,“卖股票”和“交易次数”的问题,显然使用一维dp是不能解决问题的。

我们可以使用三维 dp 来解决,dp[i][j][k],i 表示第 i 天,j 表示处于手里有股票还是没股票,k 表示已交易次数,这样看来,三维的有点头疼。

我们不妨可以使用两个二维dp来解决,f[i][j]表示手里没股票,已交易 j 次能获取的最大利润,g[i][j]表示手里有股票,已交易 j 次能获取的最大利润。

状态转移方程:f[i][j]=max(f[i-1][[j],g[i-1][j-1]+prices[i])【注意:使用g[i-1][j-1]须满足 j >=1】

                         g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]).

初始化:对于f[i][j]来说,会用到上一行的值,因此只需初始化第一行即可,由于第一行表示第一天,因此最多交易0次,对于高于0次的情况并不可能出现,初始化为 -0x3f3f3f3f.

              对于g[i][j]来说,会用到上一行的值,也可能用到前一行前一列的值(左上方)【因此不需要初始化】

填表顺序:从上到下,从左到右。

返回值:f[i][j]里面的最大值。

代码

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n=prices.size();
        vector<vector<int>> f(n,vector<int>(k+1,-0x3f3f3f3f));
        vector<vector<int>> g(n,vector<int>(k+1,-0x3f3f3f3f));
        //f[i][j] 表示没股票的时候,已经交易j次,获取的最大利润
        //g[i][j] 表示有股票的时候,已经交易j次,获取的最大利润
        f[0][0]=0,g[0][0]=-prices[0];
        for(int i=1;i<n;i++){
            for(int j=0;j<=k;j++){
                f[i][j]=f[i-1][j];
                if(j>=1)
                    f[i][j]=max(f[i][j],g[i-1][j-1]+prices[i]);
                g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]);
            }
        }
        return *max_element(f[n-1].begin(),f[n-1].end());
    }
};

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

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

相关文章

[数据集][目标检测]电力工地场景下的人头检测数据集VOC+YOLO格式7035张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;7035 标注数量(xml文件个数)&#xff1a;7035 标注数量(txt文件个数)&#xff1a;7035 标注…

(打印表格)编写程序,显示以下表格:

public class HelloWorld {public static void main(String []args) {System.out.println("a a^2 a^3");int i;for(i0;i<4;i){int j1;System.out.println(j j*j j*j*j);j;}} } 运行结果&#xff1a;

java框架树结构实现(带层级、编码、排序)

1、需求 实现一个影像资料库的功能&#xff0c;用树结构对资料进行分类 2、数据结构 通过id、pid表示父子关系 通过code表示层级关系 通过layer表示层级 通过sort进行排序 3、实体类 package org.jeecg.modules.image.entity;import com.baomidou.mybatisplus.annotation…

SQLAlchemy 模型中数据的错误表示

1. 问题背景 在使用 SQLAlchemy 0.6.0 版本&#xff08;也曾尝试使用 0.6.4 版本&#xff09;的 Pylons 应用程序中遇到了一个 SQLAlchemy ORM 问题。该问题出现在使用 psycopg2 作为数据库驱动程序、连接至 Postgresql 8.2 数据库的环境中。定义了一个 User 模型对象&#xf…

Java17 --- Mabbitmq之安装测试

目录 一、拉取运行镜像 1.1、拉取镜像环境 1.2、运行镜像 二、工作模式 2.1、消息的发送者 2.2、消息的接收者 2.3、生产队列模式 2.3.1、消息的发送者 2.3.2、消息的接收者 2.4、发布订阅模式 2.4.1、消息的发送者 2.4.2、消息的接收者 2.5、路由模式 2.5.…

记一次 .NET某工控视觉自动化系统 卡死分析

一&#xff1a;背景 1. 讲故事 今天分享的dump是训练营里一位学员的&#xff0c;从一个啥也不会到现在分析的有模有样&#xff0c;真的是看他成长起来的&#xff0c;调试技术学会了就是真真实实自己的&#xff0c;话不多说&#xff0c;上windbg说话。 二&#xff1a;WinDbg …

如何从官网下载 mysql 二进制安装包

一.下载二进行包 1. 官网网址: https://www.mysql.com/ 如图所示进入官网 2. 点击 DOWNLOADS ,进入如下图 在该页面找到 MySQL Community (GPL) Downloads 点进去 如上图页面&#xff0c;找到 MySQL Community Server 在点进去 下载 linux 通用版 点击最下面 Compressed …

你真的了解SQL语句的执行过程?

SQL查询语句的执行过程 连接器 连接器会对用户身份和访问权限进行校验。会先连接到数据库上&#xff0c;通过连接器跟客户端建立连接、获取权限、维持和管理连接。在建立连接之后&#xff0c;不会立即执行语句&#xff0c;而是将SQL语句同时传给分析器和缓存。 缓存 如果能在…

系统架构设计师【第14章】: 云原生架构设计理论与实践 (核心总结)

文章目录 14.1 云原生架构产生背景14.2 云原生架构内涵14.2.1 云原生架构定义14.2.2 云原生架构原则14.2.3 主要架构模式14.2.4 典型的云原生架构反模式 14.3 云原生架构相关技术14.3.1 容器技术14.3.2 云原生微服务14.3.3 无服务器技术14.3.4 服务网格 14.4 云原生…

linux动态调试 dev_dbg

动态调试使用方法 打开内核动态调试开关&#xff0c;make menuconfig选中CONFIG_DYNAMIC_DEBUG以及CONFIG_DEBUG_FS Linux启动后&#xff0c;使用命令行挂载上dbgfs 1. mkdir /mnt/dbg 2. mount -t debugfs none /mnt/dbg 1.控制某个文件所有dev_dbg()&#xff0c; echo -n &q…

Django里choices字段使用中文使用

如果想要将下面的表格里的内容数字换成对应的内容&#xff1a; 需要更改成这样&#xff1a; 下面是步骤&#xff1a; 在 python 里的 models.py 文件里&#xff0c;创建数据表的时候&#xff0c;用到了 choices class Example(models.Model):name models.CharField(verbose…

Ceph集群存储案例

Ceph是一种可靠的、可扩展的、统一的、分布式的存储系统。Ceph高度可靠、易于管理且免费。Ceph提供了非凡的可扩展性——数以千计的客户端访问PB到EB的数据。Ceph存储集群相互通信以动态复制和重新分配数据。目前众多云厂商都在使用Ceph&#xff0c;应用广泛。如&#xff1a;华…

SemanticKernel:添加插件

SemanticKernel介绍 Semantic Kernel是一个SDK&#xff0c;它将OpenAI、Azure OpenAI和Hugging Face等大型语言模型&#xff08;LLMs&#xff09;与C#、Python和Java等传统编程语言集成在一起。Semantic Kernel通过允许您定义插件来实现这一点&#xff0c;这些插件可以通过几行…

六、【源码】SQL执行器的定义和实现

源码地址&#xff1a;https://github.com/mybatis/mybatis-3/ 仓库地址&#xff1a;https://gitcode.net/qq_42665745/mybatis/-/tree/06-sql-executor SQL执行器的定义和实现 之前的Sql执行都是耦合在SqlSession里的&#xff0c;现在要对这部分进行解耦和重构&#xff0c;引…

CentOS 环境下 PostgreSQL 在线安装和源码安装详解

1、内容概述 昨天给大家简单的介绍了一下 PostgreSQL,并且在Windows系统上通过图形化界面的方式搭建好了环境&#xff0c;今天我们就来学习一下如何在Linux 系统上搭建 PostgreSQL环境&#xff0c;我会给大家介绍在线安装、离线源码安装以及Docker 安装三种方式。 2、在线安装…

Windows文件管理器导航窗口怎么删除第三方生成的无效导航【笔记】

Windows文件管理器导航窗口怎么删除第三方生成的无效导航【笔记】 导航窗口对应项目没有右击删除选项。 提示&#xff1a; 位置不可用 C:\Users\superman…不可用&#xff0c;如果该位置位于这台电脑上&#xff0c;请确保设备或驱动器连接&#xff0c;或者光盘已插入&#xf…

Elastic 8.14:用于简化分析的 Elasticsearch 查询语言 (ES|QL) 正式发布

作者&#xff1a;来自 Elastic Brian Bergholm 今天&#xff0c;我们很高兴地宣布 Elastic 8.14 正式发布。 什么是新的&#xff1f; 8.14 版本最重要的标题是 ES|QL 的正式发布(GA)&#xff0c;它是从头开始设计和专门构建的&#xff0c;可大大简化数据调查。在新的查询引擎的…

基于SSM+Jsp的高校二手交易平台

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

css 理解了原理,绘制三角形就简单了

1.border-位置 注意&#xff1a;border-bottom/up/right/left 主要是以三角形的结构搭建而成&#xff0c;而border也是如此。而且从边框的外围开始计算像素尺寸。在理解了这一点之后&#xff0c;绘制三角形就简单多了。 1.transparent 注意&#xff1a;该属性主要是颜色透明…

LeetCode-2938. 区分黑球与白球【贪心 双指针 字符串】

LeetCode-2938. 区分黑球与白球【贪心 双指针 字符串】 题目描述&#xff1a;解题思路一&#xff1a;贪心解题思路二&#xff1a;一次遍历统计1的个数&#xff0c;找0后累加左边的1的个数解题思路三&#xff1a; 题目描述&#xff1a; 桌子上有 n 个球&#xff0c;每个球的颜色…