算法训练营DAY48|121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

news2024/11/22 19:17:30

这一期到了买卖股票专题,买卖股票的有一些题型,可以使用贪心算法来求解,甚至有时候比动态规划更简单一些,但是本期是讲动态规划的运用,所以不做对于贪心的分析。今天只讲两道例题,其中第二题是第一题的变种,没有做过股票系列题型,我个人认为是有一定难度解题的。

121. 买卖股票的最佳时机 - 力扣(LeetCode)https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/整个数组中,我们只允许买入一只股票。给定的数组是当天的股票可以买卖多少钱,我们需要找一个合适的时机买入,再把它卖出去,以获得最大的利润。

dp数组的定义:因为是动态规划自然少不了dp数组,要想出dp数组首先并不是一件很容易的事,它不像是我们上一期的打家劫舍,可以用一维数组来记录盗取的最大金额,这里要选用二维数组来记录,当前天买股票我们能获得的最大金额,和卖出股票我们能获得的最大金额。我个人的见解是,由于我们一开始不能很快确定要哪一天买进和卖出,而且买进和卖出是应该分离开来,以便获得最大利润,所以不能用一维数组来实现。股票是否已经被买入或未被买入我们是需要一直保持记录的,它不像是打家劫舍,这一次偷盗只关乎着偷不偷上一家所得到的金额。有点扯远了,总之我们要使用二维数组,且dp【i】【0】代表了,当前第i天持有股票的状态且能获得的最大钱,dp【i】【1】代表了卖出股票所能获得最大金额,注意这里的持有不仅仅包含当天买入股票,以前买了股票,现在还没卖,那一样是拥有着股票,dp【i】【1】代表了卖出股票所能获得的最大利润。至于为什么要使它的含义表示的范围那么大,为什么不能直接的表示买入或者卖出,这是因为这样表示方便其他数组的填写,不然还要定义持有和卖完之后的情况来填满数组比较麻烦。

递推公式:递推公式是针对于两种不同状态的两个递推公式,第一个是针对持有股票的状态,我们还需要搞清一点,如何更新该值?我们知道只能购买一支股票,所以我们可以假定我们一开始有的钱数是0,买了股票是负数,卖出去了赚了钱才是正数。根据这一理念,我们需要比较的是当天如果买股票就是负的prices【i】,前一天的状态中如果持有股票,最大金额是dp【i-1】我们取它们中最大的值。前一天状态的持有股票也并不是一定是那一天买入的,而是这些天里最便宜时候买入的。

对于第二个递推公式,是尤为重要的,它是卖出股票的递推公式,而卖出股票的递推公式同样也是受两个值影响,一个是它的前一天如果卖出了股票所能获得最大钱,另一个是如果已经购买过股票的前提下,那么今天卖出去可以获得多少钱。

得出:dp【i】【0】=max(dp【i-1】【0】,-prices【i】)

dp【i】【1】=max(dp【i-1】【1】,prices【i】+dp【i】【0】)

解答一些疑问:我们如何知道已经购得股票。其实这并不需要额外的变量记载,标志,我们是否购得,这实际上是由dp【i】【0】一直在记录的,遍历的0-i之间,那一天卖的便宜哪一天就买了,同样的dp【i】【1】是管卖的,哪一天贵了得到的利润高了就会覆盖当前值,也即是两个部分是即时更新的。

而且也不会出现还没有买就卖的情况,因为i是不会向前走的,而卖股票的递推公式它也是和i有关,所以不会现在便宜买了之后,向前找贵的天卖。

dp数组初始化:dp【0】【0】应该是最开始的状态持有股票,我们把它初始化为-prices【0】。

有人要问了,第一天就买股票它如果不是最便宜一天怎么办?大家不要这样理解,因为我们会更新这个数字,但是不能将它一开始就初始化为0,这是因为上面已经说过了,初始金钱是0,你这里还初始化为0,那它永远也不会购入股票了。一直会保持0,因为只要购入股票就会得到负数比0小!!!dp【0】【1】初始化为0,因为刚第一天没有卖股票,也卖不了股票。

遍历顺序:遍历顺序自然是从前向后遍历

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

122. 买卖股票的最佳时机 II - 力扣(LeetCode)icon-default.png?t=N0U7https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/这道题和第一道题唯一的区别在于虽然股票也限定只能同时持有一支,但是在你卖出手中的股票之后,仍然可以再次购买股票,这就是和上一道题不同之处,很多人看到这里就懵了,感觉这道题很难做,其实只是上一道题改一点点代码就可以了。

这道题的dp数组定义和初始化遍历顺序都是一样的,只有递推公式求买入股票的部分不一样。在没看题解的时候,我以为递推公式这道题是只有一个的,而且可以累加的,但是其实并不是,它是通过卖出股票对买入股票的钱产生影响,从而影响了卖出股票的利润,这道题在贪心算法的运用上,思路是求取只要利润为正都相加在一起,而dp来实现思路上还是有所不同的。

递推公式:do【i】【0】=max(dp【i-1】【0】,dp【i】【1】-prices【i】)

只有这一点改动,就可以完成对于股票的重复买卖的操作,最后返回dp【prices。size()-1】【1】就可以了,为什么是这样呢?因为买入股票的第一个比较的参数,是不变的影响它的改变的参数是第二个,第二个参数是卖出股票后手里的钱如果买了当前的股票还足够多的话(比当前持有股票的钱多)那么就更新它,而卖出股票也是和当下卖的股票钱数有关,两个递推公式彼此都有关系,就造成了互相影响更新最大值,所以自然不需要累加也可以完成类似累加的操作。

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

我觉得是挺神奇的,大家好好体会一下。还有为什么第一道题的持有股票的递推公式第二个参数只是-prices【i】,我想再做一下解释。第一道题是只能买一次股票,我们是假设了初始兜里只有0元钱,而这道题可以买了再卖再买入,所以我们用的是dp【i-1】【1】,而这是什么呢?我们也可以理解为,这是目前为止我们卖股票赚的利润,用它再来买新的股票,如果不是很亏,我们就用剩下的钱减去当天的股票钱。这里的不是很亏的评价标准,也就是之前持有股票的时候拥有的钱多,还是之前未持有股票但是今天购买了拥有的钱多。这并不会一直不买,因为后面还有一句卖出股票,只要利润比你买股票大,那肯定就卖出去了,这就实现了和贪心差不多的思路,找正利润的累加起来。


第二道题,我认为有一些抽象的,需要好好理解,不要把它当作一道太简单的题来看待。

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

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

相关文章

[NeurIPS 2017] Poincaré Embeddings for Learning Hierarchical Representations

ContentsIntroductionPoincar EmbeddingsThe Limitations of Euclidean Space for Hierarchical DataEmbedding Hierarchies in Hyperbolic SpaceEvaluationReferencesIntroduction 如今&#xff0c;表征学习变得越来越重要 (e.g. word embedding, embeddings of graphs, embe…

如何在电脑上安装 Windows 版桌面编辑器 v7.3

线上编辑器的桌面端版本不需要持续的互联网连接&#xff0c;还可在计算机上处理脱机文件。因此&#xff0c;如果您需要此类功能&#xff0c;可从我们的网站中下载并安装桌面编辑器。 ONLYOFFICE桌面编辑器最新版 最近 ONLYOFFICE 发布了 v7.3&#xff0c;最新版本的桌面编辑器…

SpringBoot+Vue点餐系统

简介&#xff1a;本项目采用了基本的springbootvue设计的点餐。系统。详情请看截图。经测试&#xff0c;本项目正常运行。本项目适用于Java毕业设计、课程设计学习参考等用途。 项目描述 项目名称SpringBootVue点餐系统源码作者LHL项目类型Java EE项目 &#xff08;前后分离&a…

ESP-IDF:命令模式测试

ESP-IDF:命令模式 /命令模式/ /设计模式之开闭原则&#xff0c;对增加开放对修改关闭/ #include #include class ClientCommands{ //统一管理命令&#xff0c;这是比观察者模式多出来的地方 public: void AddMoney(){ cout<<“add money”<<endl; } void AddEqu…

图解LeetCode——1145. 二叉树着色游戏(难道:中等)

一、题目 有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中&#xff0c;给出二叉树的根节点 root&#xff0c;树上总共有 n 个节点&#xff0c;且 n 为奇数&#xff0c;其中每个节点上的值从 1 到 n 各不相同。 最开始时&#xff1a; 「一号」玩家从 [1, n] 中取一个值…

Ubuntu22.04安装nvidia显卡驱动

Ubuntu22.04安装nvidia显卡驱动 目录 方法一&#xff1a;使用官方的NVIDIA驱动进行手动安装&#xff08;稳定、靠谱&#xff09; 方法二&#xff1a;使用系统自带的“软件和更新”程序-附加驱动更新&#xff08;需要联网&#xff0c;稳定性无法验证&#xff09; 浓缩极简方法…

MySQL入门篇-视图简介

备注:测试数据库版本为MySQL 8.0 这个blog我们来聊聊MySQL视图。 前言: 视图是从一个或几个基本表导出的表。视图本身不独立存储在数据库中&#xff0c;是一个虚表。 即数据库中只存放视图的定义而不存放视图对应的数据&#xff0c;这些数据仍存放在导出视图的基本表中。 视…

[Windows] 微信超级管家,自动好友回复、计数、自动同意、群发、好友导出、消息日志、无限多开

简介 微信超级管家是一款大神针对微信制作的工具&#xff0c;它的主要功能包括了自动回复、好友计数、自动同意、群发、好友导出、消息日志、无限多开等等&#xff0c;让你拥有无限潜力哈&#xff0c;经常使用微信电脑版的朋友一定会用的上。 下载 微信超级管家 软件功能 1…

安全测试之浅析静态应用

SAST&#xff0c;Static Application Security Testing&#xff0c;即静态应用安全测试&#xff0c;也叫静态分析&#xff0c;是一种测试方法&#xff0c;一直是应用程序安全性工作的核心部分。根据Forrester的 The State Of Application Security, 2022一文的预测&#xff0c;…

云计算|OpenStack|社区版OpenStack安装部署文档(七--- 仪表盘服务dashboard的安装部署---Rocky版)

前言&#xff1a; 仪表盘是一般项目的标配&#xff0c;有了仪表盘可以降低运维工作&#xff0c;并且很多的管理工作是可以可视化的。本节计划在控制节点安装openstack官网的仪表盘项目 openstack由于是一个开源的社区版本云计算项目&#xff0c;因此&#xff0c;它的web仪表盘…

【Core】.net core 3.1 api 返回实体类数据存在null,导致小程序调用接口也直接显示了null,原来要这样设置才可

对接过API接口的小伙伴都知道&#xff0c;接口返回的Json格式数据&#xff0c;有些字段可能会出现null的情况&#xff0c;并且还是个字符串&#xff0c;直接显示在用户界面上给人感觉出bug了 文章目录【开发环境】【场景描述】【返回null值重现】1&#xff09;创建新项目2&…

细讲TCP三次握手四次挥手(二)

TCP/IP 协议族 应用层 应用层( application-layer &#xff09;的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程&#xff08;进程&#xff1a;主机中正在运行的程序&#xff09;间的通信和交互的规则。 对于不同的网络应用需要不同的应用层协议…

基本放大器电路- (一)

运算放大器组成的电路五花八门&#xff0c;令人眼花瞭乱&#xff0c;是模拟电路中学习的重点。在分析它的工作原理时倘没有抓住核心&#xff0c;往往令人头大。为此本人特搜罗天下运放电路之应用&#xff0c;来个“庖丁解牛”&#xff0c;希望各位从事电路板维修的同行&#xf…

精讲rpc框架,这么讲不怕你不明白!

谈到rpc框架可能有点陌生感&#xff0c;但是如果换成框架语言Ocaml&#xff0c;大家一定不陌生。 众所周知&#xff0c;ocaml是一款专门做functional programming的一款软件&#xff0c;尤其是它的界面非常简洁&#xff0c;还是专门的server进行线上编写。 rpc框架和ocaml是什…

一篇就看懂的文件操作

文件操作1为什么使用文件我们前面学习结构体时&#xff0c;写了通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯录中的数据自然就不存在了&#xff…

【Java并发编程】 interrupt 方法详解

【Java并发编程】 interrupt 方法详解 文章目录【Java并发编程】 interrupt 方法详解1.介绍2.打断阻塞状态线程3.打断正常状态的线程4.两阶段终止模式5.打断 park 线程1.介绍 程序中&#xff0c;有些线程的终端需要外部干预&#xff0c;比如有线程存在while(true)循环&#xf…

值得拥有并收藏的 3个安卓/鸿蒙手机解锁软件

手机无论支持哪种操作系统&#xff0c;都占据了每个人口袋里的空间。随着大量移动设备的使用&#xff0c;搜索引擎上也出现了同样数量的查询&#xff0c;其中最常见的是提供安卓/鸿蒙屏幕锁定删除工具。由于安卓是当今最畅销的设备&#xff0c;我们的首要任务是为您提供最好的安…

矿山安全生产监测预警系统 opencv

矿山安全生产监测预警系统通过pythonopencv网络模型计算机视觉技术&#xff0c;对现场画面中人的不安全行为”、“物的不安全状态”、“环境的不安全因素”三方面出发进行实时监测&#xff0c;当监测到现场画面中人员未穿反光衣行为、明火烟雾、未穿安全帽行为、矿车掉道识别、…

【王道数据结构】第三章 | 栈和队列

目录 一、栈stack 基本概念 基本操作 存储结构​​​​​​​ 二、队列Queue 基本概念 队列的基本操作 存储结构 三、栈的应用 栈在括号匹配中的应用 栈在表达式求值中的应用​编辑 栈在递归中的应用 一、栈stack 基本概念 只允许在一端(栈顶top)进行插入或删除操…

大数据看全国疫情生活,北京、武汉已过疫情拐点

自2022年11月末&#xff0c;很多地区新冠病例数据呈现下降趋势&#xff0c;与实际感知有明显差异。2022年12月14日&#xff0c;国家疾控中心发布消息&#xff0c;核酸检测实行“愿检尽检”&#xff0c;不再公布无症状感染者数据。因此&#xff0c;网友们想要了解所在地和老家的…