作者 | 王磊

来源 | 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

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

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

  1. 代码随想录贪心算法——买卖股票的最佳时机含手续费

    题目 给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :非负整数 fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每笔交易都需要付手续费.如果你已经购买 ...

  2. 算法------买卖股票的最佳时机

    题目: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格.设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票).注意:你不能同时参与多笔交易(你必须在 ...

  3. 算法-----买卖股票的最佳时机(Java 版本)

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

  4. 【每日一算法】买卖股票的最佳时机

    微信改版,加星标不迷路! 每日一算法-买卖股票的最佳时机 作者:阿广 阅读目录 1 题目 2 解析 1 题目 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔 ...

  5. 【算法】贪心算法:LeetCode 714 买卖股票的最佳时机含手续费 、LeetCode 968 监控二叉树

    LeetCode 714 买卖股票的最佳时机含手续费 (中等) 题目 描述 给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :整数 fee 代表了交易股票的手续费用. 你 ...

  6. 力扣算法JS LC [714. 买卖股票的最佳时机含手续费] LC [968. 监控二叉树]

    LC 714. 买卖股票的最佳时机含手续费 给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 :整数 fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你 ...

  7. 【贪心算法】Leetcode 714. 买卖股票的最佳时机含手续费

    [贪心算法]Leetcode 714. 买卖股票的最佳时机含手续费 题目 给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 :整数 fee 代表了交易股票的手续费用. ...

  8. 算法训练Day49 | Leetcode121. 买卖股票的最佳时机(只能买卖一次);LeetCode122. 买卖股票的最佳时机II(可以买卖多次)

    目录 Leetcode121. 买卖股票的最佳时机 方法一:暴力解法 1. 思路 2. 代码实现 3. 复杂度分析 4. 思考与收获 方法二:贪心算法 1. 思路 2. 代码实现 3. 复杂度分析 方 ...

  9. 算法训练第五十天 | 123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV

    动态规划part11 123.买卖股票的最佳时机III 题目描述 思路 拓展 188.买卖股票的最佳时机IV 题目描述 思路 易错点 123.买卖股票的最佳时机III 题目链接:123.买卖股票的最佳 ...

最新文章

  1. “因为这 4 个回答,我决定录用这位软件工程师!”
  2. 溃不成军:科通芯城一度再跌近30% 股价三天腰斩
  3. 关键词优化一定要从正规渠道入手
  4. poj 3352 双连通分量
  5. 200米外遥测心跳定身份,五角大楼全新黑科技,人脸伪装也没用
  6. php怎样获取视频播放的进度条,小程序如何实现视频或音频自定义可拖拽进度条...
  7. Akka并发编程——第五节:Actor模型(四) 停止Actor
  8. hexo的yelee主题中的标签字体大小的修改
  9. 谈谈 SAP 产品 UI 开发中的组件概念
  10. 创建自己的Java批注
  11. MATLAB 求曲线长度
  12. NOIP2014 写后感
  13. Spring : Bean依赖注解(@DependsOn)
  14. 智驾科技MAXIEYE完成3亿元B轮融资,暂未取得品牌同名商标
  15. 自己动手破解斯凯Mrp游戏
  16. librdkafka安装步骤
  17. *rock ,scissors ,paperpku 2339
  18. 微信小程序学习笔记——环境准备 【注册账号】【获取APPID】
  19. 7-2 新胖子公式 (5 分)
  20. Matplotlib中显示汉字,Times New Roman字体,公式的相关设置(1)

热门文章

  1. mysqlreport的学习
  2. 【并查集+dp】Team
  3. 第 11 章 日志管理 - 089 - 初探 ELK
  4. Logistic回归和SVM的异同
  5. XenDesktop 5.5 – HDX RealTime TCP UDP Audio演示
  6. hadoop-0.21.0-eclipse-plugin无法在eclipse中运行解决方案
  7. python发短信脚本_python脚本发送短信
  8. 用计算机算出陈赫手机号码,陈赫手机号码遭《快本》曝光,并被网友打到关机!还有人搜到了他的支付宝账户......
  9. 计算机控制系统a卷-答案,计算机控制系统2010-2011年试题A答案
  10. java 责任链模式 链表_责任链模式的实现及源码中应用