【算法练习Day41】买卖股票的最佳时机买卖股票的最佳时机 II

news2024/11/23 15:01:21

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 买卖股票的最佳时机
  • 买卖股票的最佳时机 II
  • 总结:

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

买卖股票的最佳时机

121. 买卖股票的最佳时机 - 力扣(LeetCode)

整个数组中,我们只允许买入一只股票。给定的数组是当天的股票可以买卖多少钱,我们需要找一个合适的时机买入,再把它卖出去,以获得最大的利润。

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];
    }
};

买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II - 力扣(LeetCode)

这道题和第一道题唯一的区别在于虽然股票也限定只能同时持有一支,但是在你卖出手中的股票之后,仍然可以再次购买股票,这就是和上一道题不同之处,很多人看到这里就懵了,感觉这道题很难做,其实只是上一道题改一点点代码就可以了。

这道题的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】,而这是什么呢?我们也可以理解为,这是目前为止我们卖股票赚的利润,用它再来买新的股票,如果不是很亏,我们就用剩下的钱减去当天的股票钱。这里的不是很亏的评价标准,也就是之前持有股票的时候拥有的钱多,还是之前未持有股票但是今天购买了拥有的钱多。这并不会一直不买,因为后面还有一句卖出股票,只要利润比你买股票大,那肯定就卖出去了,这就实现了和贪心差不多的思路,找正利润的累加起来。

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

总结:

今天我们完成了买卖股票的最佳时机、买卖股票的最佳时机 II 两道题,相关的思想需要多复习回顾。接下来,我们继续进行算法练习。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

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

相关文章

办公神器!2024年值得拥有的10款在线画板软件!

随着科技的进步和互联网的普及&#xff0c;我们工作、学习和生活方式发生了翻天覆地的变化。在线画板软件就是在这个背景下应运而生的一种便捷工具。它不仅满足了我们随时随地绘制图像、演示思路的需求&#xff0c;还提供了协同编辑、云存储等功能&#xff0c;使得团队协作变得…

Java面试题(高频、有答案,全网最强)

原文网址&#xff1a;Java面试题&#xff08;高频、有答案&#xff0c;全网最强&#xff09;-CSDN博客 这是一套全网最强的Java面试题&#xff0c;吊打网上所有Java面试题。 此套面试题的威力&#xff1a;看过这套题的朋友、同事、粉丝参加了面试后说&#xff0c;他们面试被问…

基于C#的GRPC

GRPC gRPC&#xff08;gRPC Remote Procedure Call&#xff09;是由Google开发的高性能、跨语言的远程过程调用框架。它基于HTTP/2协议进行通信&#xff0c;支持多种编程语言&#xff0c;包括C, C#, Java, Python等&#xff0c;使不同语言的应用程序可以通过远程调用相互通信。…

SPASS教程-入门

常用的统计工具 EXCEL 严格说来并不是统计软件&#xff0c;但作为数据表格软件&#xff0c;有一定统计计算功能。对于简单分析&#xff0c;Excel还算方便&#xff0c;但随着问题的深入&#xff0c;Excel就不那么“傻瓜”&#xff0c;需要使用函数&#xff0c;甚至根本没有相应…

​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】 课本里章节里所有蓝色字体的思维导图

Spire.Office for Java 8.10.2 同步更新Crk

Spire.Office for Java 是 E-iceblue 提供的企业级 Office Java API 的组合。它包括Spire.Doc for Java、Spire.XLS for Java、Spire.Presentation for Java、Spire.PDF for Java和Spire.Barcode for Java。 开发人员可以使用Spire.Office for Java在Java应用程序中执行各种办…

【electron】【附排查清单】记录一次逆向过程中,fetch无法请求http的疑难杂症(net::ERR_BLOCKED_BY_CLIENT)

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ Adblock等插件拦截2️⃣ 【失败】Content-Security-Policy启动服务器json-serverhtml中的meta字段 3️⃣ 【失败】https vs httpwebPreferences & allowRunningInsecureContent disable-features 4️⃣ 【失败】检测fetch…

技术分享 | app自动化测试(Android)--元素定位方式与隐式等待

元素定位是 UI 自动化测试中最关键的一步&#xff0c;假如没有定位到元素&#xff0c;也就无法完成对页面的操作。那么在页面中如何定位到想要的元素&#xff0c;本小节讨论 Appium 元素定位方式。 Appium的元素定位方式 定位页面的元素有很多方式&#xff0c;比如可以通过 I…

初识Java 17-2 反射

目录 转型前检查 构建例子&#xff1a;生成层次结构 优化Creator&#xff1a;使用类字面量 优化PetCounter&#xff1a;动态验证类型 更通用的递归计数 注册工厂 本笔记参考自&#xff1a; 《On Java 中文版》 转型前检查 当我们使用传统的类型转换&#xff0c;例如&…

实战!工作中常用的设计模式

文章目录 前言一、策略模式1.1、 业务场景1.2 、策略模式定义1.3、 策略模式使用1.3.1、一个接口&#xff0c;两个方法1.3.2、不同策略的差异化实现1.3.3、使用策略模式 二、责任链模式2.1、业务场景2.2、责任链模式定义2.3、责任链模式使用2.3.1、一个接口或者抽象类2.3.2、每…

11.7加减计数器,可置位~,数字钟分秒,串转并,串累加转并,24位串并128,流水乘法器,一些乘法器

信号发生器 方波&#xff0c;就是一段时间内都输出相同的信号 锯齿波就是递增 三角波就是先增后减 加减计数器 当mode为1则加&#xff0c;Mode为0则减&#xff1b;只要为0就输出zero 这样会出问题&#xff0c;因为要求是十进制&#xff0c;但是这里并没有考虑到9之后怎么办&a…

openvino学习(一)ubuntu20.04安装openvino2022

安装openvino2022要求 操作系统 Ubuntu 18.04 长期支持 (LTS)&#xff0c;64 位 Ubuntu 20.04 长期支持 (LTS)&#xff0c;64 位 软件 CMake 3.13 或更高版本&#xff0c;64 位 GCC 7.5.0&#xff08;适用于 Ubuntu 18.04&#xff09;或 GCC 9.3.0&#xff08;适用于 Ubunt…

工具介绍——第三方软件远程连接(工具:Rustdesk)

文章目录 前言一、使用工具二、开始演示1、拿下目标主机权限后上传文件2、运行目标主机上的rustdesk-1.1.9.exe文件3、目标主机上whoami查看现在的用户4、查找目标主机上连接的文件&#xff0c;并添加连接密码5、目标主机重启rustdesk的应用程序6、本地连接主机 前言 这里主要…

“第六十三天”

这两天怎么做的这么别扭&#xff0c;为什么我的vs 的strlen函数包括终止字符了&#xff1b; 哦哦&#xff0c;明白了&#xff0c;fgets函数读取在未达到指定字长&#xff0c;或者遇见空白符之前&#xff0c;会读取前面的所有字符&#xff0c;所以会读取换行符&#xff0c;而get…

康耐视深度学习ViDi-View菜单介绍

Accept View承认当前图片标注的有效性 Clear Marking 清除当前图片的标注特征 Clear Marking & Labels清除当前图片的标注特征和标签 Process处理当前图片 Edit ROI编辑检测的区域 Edit Regions编辑(标注)特征区域 Edit Mask 编辑遮挡(屏蔽)区域 Apply Mask To Tool将遮挡(…

杨辉三角(Java实现)

public class Demo09 {public static void main(String[] args) {//第一位和最后一位都为1//除了每行的第一列之外,其余的数为a[i][j]aa[i-1][j]a[i-1][j-1];int[][] arrays new int[10][10];for(int i 0;i<10;i){if(i0){ //第一行直接赋值为0arrays[i][0]1;continue;//重…

深入理解强化学习——多臂赌博机:基于置信度上界的动作选择

分类目录&#xff1a;《深入理解强化学习》总目录 因为对动作—价值的估计总会存在不确定性&#xff0c;所以试探是必须的。贪心动作虽然在当前时刻看起来最好&#xff0c;但实际上其他一些动作可能从长远看更好。 ϵ − \epsilon- ϵ−贪心算法会尝试选择非贪心的动作&#xf…

ZipInputStream解压报错java.lang.IllegalArgumentException: MALFORMED

背景 使用jdk自带的zip工具ZipInputStream&#xff0c;去读取使用winrar在中文windows制作出来的zip文件报错。 Exception in thread "main" java.lang.IllegalArgumentException: MALFORMEDat java.util.zip.ZipCoder.toString(ZipCoder.java:58)at java.util.zip…

Qwt QwtWheel绘制滚动轮

1.简介 QwtWheel 是一个用于实现滚动轮控件的类库。它基于 Qt 框架&#xff0c;并提供了一些方便的功能来处理滚动轮的事件和绘图。 QwtWheel 类继承自 QWidget类&#xff0c;用于定义滚动轮控件的通用行为。QwtWheel 添加了特定于滚动轮的功能。 QwtWheel 可以用于创建具有滚…

Spring Cloud之多级缓存

目录 传统缓存 多级缓存 JVM进程缓存 Caffeine 缓存驱逐策略 实现进程缓存 常用Lua语法 数据类型 变量声明 循环使用 定义函数 条件控制 安装OpenResty 实现Nginx业务逻辑编写 请求参数解析 实现lua访问tomcat JSON的序列化和反序列化 Tomcat的集群负载均衡 …