小白学算法:买卖股票的最佳时机!

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

本文已收录至 Github《小白学算法》系列:https://github.com/vipstone/algorith

今天蚂蚁集团(支付宝)正式上市了,毫无疑问这一举措又造就了一大批富豪,然而作为局外人的我们,也只有羡慕的份了。明明可以靠运气吃饭,咱非得靠实力,你说亏不亏啊?

但话又说回来,能进蚂蚁的人也都是牛人,那咱也赶紧提升一下技能吧,好为下一个“蚂蚁”做足准备。

今天的这道题比较有意思,是关于「买卖股票」的,题目如下。

题目描述

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]

输出: 5

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。    注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入: [7,6,4,3,1]

输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

来源:LeetCode

剑指 offer 64:https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof/submissions/难度:中

leetcode 121:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/难度:简单

解题思路

根据题目的意思我们知道,我们只有一次交易的机会,也就是买一次再卖一次,但同时要保证收益最大化。那我们本能的直觉是在最低的价格买入,再在最高的价格卖出就好了,如下图所示:


但这有一个问题,就是我们要保证最高价格要在最低的价格之后,因为我们必须在购买了股票之后才能卖出,而不是相反的顺序,这就让问题变的复杂了。

但此刻我们想到了一个最直接也是最笨的一个方法,那就是用暴力穷举法,我们使用两层循环,依次在每个节点买入,然后再在之后的所有节点卖出,这样来计算节点间的差值(收益),如果此差值大于当前最高收益,就将此值设置为当前最高收益,这样循环完,我们就能获得最大收益了。如下图所示:


方法一:暴力法

有了上面的思路,接下来我们用代码实现一下:

class Solution {public int maxProfit(int[] prices) {int mp = 0; // 最高收益for (int i = 0; i < prices.length; i++) {for (int j = i + 1; j < prices.length; j++) {int item = prices[j] - prices[i];if (item > mp) mp = item;}}return mp;}
}

可以看出代码还是很简单的,但别高兴得太早,我们来看它在 leetcode 上的表现:

复杂度分析

  • 时间复杂度:O(n^2),循环运行 n(n-1)/2 次。

  • 空间复杂度:O(1),只使用了常数位的变量。

真是一顿操作猛如虎,最终击败百分之五!如果用这种代码去面试的话,估计只能回去等通知了。那有没有更好的方法呢?答案是肯定的,继续往下看。

方法二:遍历一次

对于这道题我们其实可以使用一次循环来实现,先来看下面的这张折线图:


从上面的图片我们可以看出,我们在每个节点其实只会做两件事(第一个节点除外,只能买入不能卖出),这两件事分别是:买入或卖出。那么我们其实可以用一个循环来计算出最大的利润,我们只需要依次对于每个节点做以下两个判断:

  • 判断当前节点是不是相对最低价,如果是,则将它设置为最低价(也就是买入);

  • 如果当前节点不是最低价,那我们就将它卖出,然后计算卖出的收益(当前节点减去相对最低价),如果卖出的收益大于目前的最高收益,则将此值设置为最高收益。

这样循环完成之后最高收益就出来了,实现代码如下:

class Solution {public int maxProfit(int prices[]) {if (prices == null || prices.length == 0) return 0;int mp = 0; // 最高收益int min = prices[0]; // 最低价for (int i = 1; i < prices.length; i++) {if (prices[i] < min) {// 设定相对最低价min = prices[i];} else if (mp < (prices[i] - min)) {// 设定最高盈利mp = prices[i] - min;}}return mp;}
}

以上代码在 leetcode 中的结果如下图所示:

复杂度分析

  • 时间复杂度:O(n),只需要遍历一次。

  • 空间复杂度:O(1),只使用了常数个变量。

从以上的执行的结果可以看出,这段代码还算是比较理想的,这样面试官也会对你竖起大拇指了。

总结

本文我们计算了单次(一次买入和卖出)股票的最高收益,刚开始我们使用的是最简单粗暴的暴力枚举法,使用两层循环依次相减来求出最高收益值,但这种方法的执行效率太低。

然后我们经过观察折线图发现,只需要一次循环也能找出最高的收益值。我们只需要在每个节点做两个判断,第一:判断此节点是否为相对最小值,如果是,则记录下来;如果不是,则计算此值和相对最小值是否为当前最高收益,如果是,则记录下来。那么循环一圈之后,我们就能得出最高的收益了,并且执行的效率也很高。

你学会了吗?有不懂的地方或者更好的方法,欢迎评论区留言~


往期推荐

算法图解:如何用两个栈实现一个队列?

2020-10-26

Java中的5大队列,你知道几个?

2020-10-24

一文详解「队列」,手撸队列的3种方法!

2020-10-21

关注我,每天陪你进步一点点!

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

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

相关文章

《APUE》第6章笔记

这一章主要介绍了口令文件和组文件的结构和一些围绕这些结构的函数。 口令文件即passwd就是在/etc/passwd中可以查阅。其结构是&#xff1a; 上图四个平台能支持的就用黑点表示。 因为加密口令这一项放在passwd这个人人可读的文件中&#xff0c;可能会有安全问题。所以现在的Li…

聊聊近期的感受和10月文章精选!

先来看本月的原创文章汇总&#xff0c;其中算法部分也有少量 9 月份的文章&#xff0c;这样汇总起来大家看起来更方便&#xff0c;目录如下。算法系列小白学算法第1篇&#xff1a;一文详解「栈」和手撸栈的两种方法&#xff01;小白学算法第2篇&#xff1a;JDK 竟然是这样实现栈…

第六章关系数据理论

第六章关系数据理论6.1_问题的提出&#xff08;略&#xff09;6.2_规范化6.2.1_函数依赖6.2.2_码6.2.3_范式6.2.4_2NF6.2.5_3NF6.2.6_BCNF6.2.7_多值依赖6.2.8_4NF6.2.9_规范化小结6.3_Armstrong公理系统6.3.1_函数依赖闭包6.3.2_最小依赖集6.3.3_转换为3NF的保持函数依赖的分解…

Github上的热门iOS开源项目:AFNetworking、MagicalRecord、BlocksKit以及XVim

1. AFNetworking AFNetworking是一个非常受欢迎的轻量级的iOS、Mac OS X网络通信类库。它建立在NSURLConnection、NSOperation以及其技术的基础上&#xff0c;有着精心设计的模块结构和功能丰富的API&#xff0c;让很多网络通信功能的实现变得十分简单。 附件&#xff1a;/c…

队列实现栈的3种方法,全都击败了100%的用户!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;本文已收录至 Github《小白学算法》系列&#xff1a;https://github.com/vipstone/algorith之前我们讲过《用两个栈实现一个…

where、having、group by、order by、count的使用注意

where、having、group by、order by、count的使用注意1_where、having、group by、order by的顺序2_group by的作用3_where和group by的组合4_group by和having的组合5_where、having、group by的组合使用6_count与group by的组合使用1_where、having、group by、order by的顺序…

很实用的21个SQL小技巧!

前言每一个好习惯都是一笔财富&#xff0c;本文基于MySQL&#xff0c;分SQL后悔药&#xff0c; SQL性能优化&#xff0c;SQL规范优雅三个方向&#xff0c;分享写SQL的21个好习惯&#xff0c;谢谢阅读&#xff0c;加油哈~1. 写完SQL先explain查看执行计划&#xff08;SQL性能优化…

阿里最喜欢问的多线程顺序打印的5种解法!

Keeper导读大家在换工作面试中&#xff0c;除了一些常规算法题&#xff0c;还会遇到各种需要手写的题目&#xff0c;所以打算总结出来&#xff0c;给大家个参考。全文 2929 字&#xff0c;剩下的是代码&#xff0c;P6 及以下阅读只需要 8 分钟&#xff0c;高 P 请直接关闭第一篇…

CSS入门

CSS入门1_CSS概要1.1_CSS引入方式2_CSS选择器3_字体样式3.1_字体属性3.2_字体类型&#xff1a;font-family3.3_字体大小&#xff1a;font-size3.4_字体粗细&#xff1a;font-weight3.5_字体颜色&#xff1a;color3.6_总结4_文本样式4.1_文本样式属性4.2_首行缩进&#xff1a;te…

23张图!万字详解「链表」,从小白到大佬!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;链表和数组是数据类型中两个重要又常用的基础数据类型。数组是连续存储在内存中的数据结构&#xff0c;因此它的优势是可以通…

何为“秒传”

写在前面 最近一直在弄文件传输的组件&#xff0c;在讨论组里面&#xff0c;有同事提到“秒传”的功能。在目前的通信软件中也有网盘的功能&#xff0c;就从网上搜了一下&#xff0c;这里对“秒传”的实现思路做一下总结&#xff0c;在之后会写一个小的demo实现一下。没有其他&…

数组转List的3种方法和使用对比!

作者 | 大脑补丁来源 | blog.csdn.net/x541211190/article/details/79597236前言&#xff1a;本文介绍Java中数组转为List三种情况的优劣对比&#xff0c;以及应用场景的对比&#xff0c;以及程序员常犯的类型转换错误原因解析。一.最常见方式&#xff08;未必最佳&#xff09;…

oracle10g备份导入

2019独角兽企业重金招聘Python工程师标准>>> //导出 exp test/testgdsoft filed:\gd.dmp //删用户 drop user wkwx cascade; //用PLSQL创建数据数据库 create user hzjzjn identified by hzjzjn default tablespace BDP_DATABD; grant CREATE USER,DROP USER,ALTE…

VisualSVNServer的使用

VisualSVNServer的使用1_服务端初识1.1_创建新仓库1.2_创建用户并分配权限1_服务端初识 1.1_创建新仓库 右击Repository&#xff0c;点击create 点击下一步 输入仓库名 右击空白处&#xff0c;点击新建&#xff0c;点击project structure 输入工程名 1.2_创建用户并分…

安利一个IDEA骚操作:一键生成方法的序列图

在平时的学习/工作中&#xff0c;我们会经常面临如下场景&#xff1a;阅读别人的代码阅读框架源码阅读自己很久之前写的代码。千万不要觉得工作就是单纯写代码&#xff0c;实际工作中&#xff0c;你会发现你的大部分时间实际都花在了阅读和理解已有代码上。为了能够更快更清晰地…

c#中textbox属性_C#.Net中带有示例的TextBox.Multiline属性

c#中textbox属性Here we are demonstrating use of Multiline property of the TextBox Control. 在这里&#xff0c;我们演示了TextBox控件的Multiline属性的使用。 Multiline property contains two values: 多行属性包含两个值&#xff1a; True: We can enter text in mo…

MATLAB新手教程

MATLAB新手教程 1&#xff0e;MATLAB的基本知识 1-1、基本运算与函数 在MATLAB下进行基本数学运算&#xff0c;仅仅需将运算式直接打入提示号&#xff08;>>&#xff09;之後&#xff0c;并按入Enter键就可以。比如&#xff1a; >> (5*21.3-0.8)*10/25 an…

嗯,查询滑动窗口最大值的这4种方法不错....

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;本文已收录至 Github《小白学算法》系列&#xff1a;https://github.com/vipstone/algorithm这是一道比较基础的算法题&…

SVN客户端使用

SVN客户端使用1. 复制服务端URL2. 在客户端电脑新建文件夹用于存储版本代码3. 右击空白处&#xff0c;checkout4. 进入trunk目录&#xff0c;即可尝试新建文件并上传到服务端4.其他客户端更新版本5.解决代码冲突期间由于之前登陆过并设置为记住密码&#xff0c;所以整个过程并没…

25 张图,1.4 w字!彻底搞懂分布式事务原理

本文提纲如下&#xff1a;0. 前言1. 单数据源事务 & 多数据源事务2. 常见分布式事务解决方案2.1. 分布式事务模型2.2. 二将军问题和幂等性2.3. 两阶段提交&#xff08;2PC&#xff09; & 三阶段提交&#xff08;3PC&#xff09;方案2.4. TCC 方案2.5. 事务状态表方案2.…