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

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

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

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

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

题目描述

给定一个数组,它的第 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/
难度:简单

解题思路

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

image.png

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

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

image.png

方法一:暴力法

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

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 上的表现:

image.png

复杂度分析

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

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

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

方法二:遍历一次

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

image.png

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

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspjyz.html