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

买卖股票的最佳时机

分析

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

如果尝试使用暴力解法,时间复杂度为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.mzph.cn/web/23096.shtml

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

相关文章

金士顿U盘被写保护的解决方法

1.适用的U盘芯片信息 USB设备ID: VID 0951 PID 1666 设备供应商: Kingston 设备名称: DataTraveler 3.0 设备修订版: 0110 产品制造商: Kingston 产品型号: DataTraveler 3.0 产品修订版: PMAP 主控厂商: Phison(群联) 主控型号: PS2251-07(PS2307) - F/W 08.03.50 [2018-…

从学士-硕士-博士-博士后-副教授-教授-优青-杰青-长江-院士:一文看懂学术巨人的成长历程

会议之眼 快讯 学术之路&#xff0c;如同攀登一座高耸入云的山峰&#xff0c;需要毅力、智慧和不断的求知探索。从奠定基础的学士&#xff0c;到站在学术巅峰的院士。这条成长之路充满了挑战和机遇。 如果把学术界比作王者荣耀&#xff0c;那么学者们的成长历程就像是在进行一…

SpringBoot-SchedulingConfigurer源码初识:理解定时任务抛异常终止本次调度,但不会影响下一次执行调度

SchedulingConfigurer源码初识&#xff1a;理解定时任务抛异常终止本次调度&#xff0c;但不会影响下一次执行调度 EnableSchedulingScheduledAnnotationBeanPostProcessor进入finishRegistration方法 ScheduledTaskRegistrar处理触发器任务&#xff08;TriggerTask&#xff09…

F5G城市光网,助力“一网通城”筑基数字中国

《淮南子》中说&#xff0c;“临河而羡鱼&#xff0c;不如归家织网”。 这句话在后世比喻为做任何事情都需要提前做好准备&#xff0c;有了合适的工具&#xff0c;牢固的基础&#xff0c;各种难题也会迎刃而解。 如今&#xff0c;数字中国发展建设如火如荼&#xff0c;各项任务…

训练营第二十七天 | 491.递增子序列46.全排列47.全排列 II332.重新安排行程51. N皇后

491.递增子序列 力扣题目链接(opens new window) 给定一个整型数组, 你的任务是找到所有该数组的递增子序列&#xff0c;递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 说明: …

Python脚本自动填充数据和生成文档轻松办公

一&#xff0c;自动填充数据生成word文档 代码&#xff1a; from docx import Document# 创建一个新的Word文档对象 doc Document()# 添加标题 doc.add_heading(自动填充数据和生成文档, level1)# 添加段落 doc.add_paragraph(这是一个使用Python脚本自动填充数据并生成文档的…

刷新方盒子最快10万销量纪录 捷途旅行者何以颠覆越野市场?

近年”方盒子“产品迅速崛起&#xff0c;在新一轮的市场角逐中&#xff0c;率先突围的并非传统豪强&#xff0c;而是首次进军越野市场的捷途汽车。作为“燃油车&#xff0c;”捷途旅行者&#xff0c;在面对纯电、混动等产品的强势围剿下&#xff0c;仅用时9个月便成为细分市场销…

基于细节增强卷积和内容引导注意的单图像去雾

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;DEA-Net&#xff1a;基于细节增强卷积和内容引导注意的单图像去雾1、研究背景2、方法提出3、相关知识3.1、DEConv3.3、多重卷积的…

C语言指针与数组名的联系

目录 一、数组名的理解 a.数组名代表数组首元素的地址 b. 两个例外 二、使用指针来访问数组 三、一维数组传参的本质 一、数组名的理解 a.数组名代表数组首元素的地址 我们在使用指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,…

枚举(enum)+联合体(union)

枚举联合 一.枚举类型1.枚举类型的声明2.枚举类型的优点3.枚举类型的使用 二.联合体1.联合体类型的声明2.联合体的特点3.相同成员的结构体和联合体对比4.联合体大小的计算5.联合体的练习&#xff08;判断大小端&#xff09;6.联合体节省空间例题 一.枚举类型 1.枚举类型的声明…

Sentinel1.8.6更改配置同步到nacos(项目是Gateway)

本次修改的源码在&#xff1a;https://gitee.com/stonic-open-source/sentinel-parent 一 下载源码 地址&#xff1a;https://github.com/alibaba/Sentinel/releases/tag/1.8.6 二 导入idea&#xff0c;等待maven下载好各种依赖 三 打开sentile-dashboard这个模块&#xf…

华为手机录屏在哪里?图文详解帮你找!

随着科技的进步&#xff0c;智能手机已成为我们日常生活中不可或缺的工具。其中&#xff0c;华为手机凭借其卓越的性能和用户体验&#xff0c;在全球范围内赢得了广泛的赞誉。在众多功能中&#xff0c;录屏功能尤为实用&#xff0c;无论是制作教程、记录游戏精彩瞬间&#xff0…

压敏电阻器是在规定温度下,当电压超过某一临界值时电导随电压的升高而急速增大的一种电阻器

压敏电阻器是在规定温度下,当电压超过某一临界值时电导随电压的升高而急速增大的一种电阻器。压敏电阻器的伏安特性是非线性的,因此,压敏电阻器亦称为非线性电阻器,非线性来自于压敏电阻器两端的外加电压,其伏安特性如图 9-1所示。从图9-1可以看出,压敏电阻器有对称型和非对称型…

网络运维简介

目录 1.网络运维的定义 2.诞生背景 3.网络运维的重要性 4.优点 5.缺点 6.应用场景 6.1.十个应用场景 6.2.数据中心运维 7.应用实例 8.小结 1.网络运维的定义 网络运维&#xff08;Network Operations&#xff09;是指管理、监控和维护计算机网络以确保其高效、安全和…

Python私教张大鹏 Vue3整合AntDesignVue之文本组件

案例&#xff1a;展示标题 核心代码&#xff1a; <a-typography><a-typography-title>Introduction</a-typography-title> </a-typography>vue3示例&#xff1a; <template><a-typography><a-typography-title>这是一个标题</…

【K8s】专题四(6):Kubernetes 控制器之 Job

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、基本介绍 二、工作原理 三、相关特性 四、资源清单&#xff08;示例&#xff09; 五…

电路分析答疑 1

三要素法求解的时候&#xff0c; 电容先求U&#xff0c;再利用求导求I 电感先求I&#xff0c;再利用求导求U 若I的头上没有点点&#xff0c;那就是求有效值 叠加定理&#xff0c;不要忘记 若电流值或者电压值已经给出来了&#xff0c;那就说明这一定是直流电。 在画画圈的时候…

数据库(25)——多表关系介绍

在项目开发中&#xff0c;进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;各个表之间的结构基本上分为三种&#xff1a;一对多&#xff0c;多对多&#xff0c;一对一。 一对多 例如&#xff0c;一个学校可以有…

Mac修改Mysql8.0密码

转载请标明出处&#xff1a;http://blog.csdn.net/donkor_/article/details/139392605 文章目录 前言修改密码Step1:修改my.conf文件Step2:添加配置skip-grant-tablesStep3:重启mysql服务Step4:进入mysqlStep5:刷新权限Step6:修改密码Step7:再次刷新权限Step8:删除/注释 skip-…

DNS域名

DNS域名 DNS是域名系统的简称 域名和ip地址之间的映射关系 互联网中&#xff0c;ip地址是通信的唯一标识 访问网站&#xff0c;域名&#xff0c;ip地址不好记&#xff0c;域名朗朗上口&#xff0c;好记。 域名解析的目的就是为了实现&#xff0c;访问域名就等于访问ip地址…