leetcode-买卖股票的最佳时机

        本次分享一道经典的算法题,准确的说是一道题的不同条件下的不同求法。这道题一共有六种情况,每种情况都是不同的解法,在leetcode上对应六道题:

        前两题为这个系列的基础,也是引导之后解法思维方式的关键。

第一题,只能交易一次

        第一题的题目如下:

        在拿到题目之后,首先需要确定的是:买入股票的时候一定在卖出之前,体现在我们的参数上就是买入的时候的价格在数组中的序号是小于卖出的价格在数组中的序号的。

        因为确定了上面的这个思路,所以我拿到题目后首先想到的是:我只要知道在每个位置上,在这个位置之前最小的数和这个位置之后最大的数,就可以通过差值计算拿到在该位置左右进行买入卖出能拿到的最大利润。

        首先从实现上来说,这样子解这道题肯定是没有问题的,只需要最多进行三次循环:正循环一次,记录到每个位置时能买入的最低值;反着循环一次,记录到每个位置时,在这个位置之后会出现的最大卖出值;再循环一次,计算每个位置上在左边买右边卖能赚到的最大值。简单优化后,可以将三次循环减少为两次:正向扫描一次找到所有位置左边的最小值。反着扫描的时候,在拿到该位置右边的最大值的时候,直接与左边的最小值求差。但即便这样,在此题上消耗的时间最少为2N,空间最少为N(N为数组的长度,空间消耗最小为一个用来存储到每个位置时左边最小值的数组)。

        其实这道题不论从时间还是空间上,都还能有很大的优化空间:

        上面我们已经知道了,买入一定发生在卖出之前,即买入的价格在数组中的序号一定是小于卖出的价格在数组中的序号的。同时,我们希望买入的价尽可能的小,而卖出的价尽可能的高。

        由“买入一定在卖出左边”这里想到,是不是只进行一次循环就可以了。所以可以从数组的第一个数开始向后思考:

        我们用两个变量来记录两个值,一个值是我们到目前为止碰到的最小的数(到目前为止可以买入的最低价),另一个变量用来记录我们到目前为止已经完成买入卖出的话可以赚到的最大值。从第一个数开始向最后循环,每碰到一个数,如果这个数比我们存的最小买入价更小,我们更新最小买入价,这个值可以在之后卖出的时候提供一个更小的买入价。如果当前碰到的价格比现在存的最小买入价要大,我们就计算如果现在卖出可以赚到的数值,然后与我们记录的在之前的最大差值,如果更大的话就更新。这样在扫描了一遍之后,我们记录差值的变量就必然会被更新成为最小买入与最大卖出的差值。python代码实现如下:

第二题,不限制交易次数

        第二题与第一题的区别在于,题目的限制由只能买卖一次变成了可以进行无数次的买卖,但是同时只能有一笔交易在进行中,即只有将之前买的卖出之后,才能进行下一次的买入。

        既然可以进行无数次的交易,那么我们需要考虑的就是“用最少的时间和空间将所有的利润都获取到”。

        因为在第一题中我们已经实现了只扫描一次的算法,所以现在我们仍然在只扫描一次的基础上思考如何拿到所有可以赚到的差值。

        当我们扫描到位置 i 的时候,如果price[i]是大于price[i - 1]的,那么这个差值就可以作为我们赚到的。因为我们不需要考虑交易次数的限制,所以我们一定可以通过通过交易拿到这个差值。如果price[i]小于price[i - 1]那么我们认为在之前的交易已经结束了,我们更新我们的买入价,之后遇到较高的价的时候,与当前的低买入价求差。我们的宗旨是:只要在涨,就赚下差值,只要跌了,就重新开始。因为我们碰到下面这种情况的时候,x1+x2一定是大于x3的,所以一旦我们在扫描的时候发现当前值就变小了,就开始重新算差值。

        具体python实现如下:

第三题,最多交易两次

        第三题的限制是最多进行两次交易,同一时间只能有一笔交易存在。

        因为两笔交易相对独立,因为我们有第一题的基础,所以我们可以将这题进行拆解:找到一个位置,在这个位置左边完成一次交易,右边完成一次交易,得到两次交易的差值之和。

        在第一题中,我们从提一个数开始向后扫描,扫到哪个位置就能得到一直到那个位置我们完成一次交易所能得到的最大差值。所以在此题中可以进行正反两次扫描,分别获得每个位置前面完成一次交易所能得到的最大差值和后面完成一次交易能得到的最大值。然后计算所有位置上两次交易得到的结果,取到最大值,就是此题的答案。

扩展

        通过以上三题,我们可以发现题目中真正限定的其实就是交易的次数。虽然三道题的实现过程都不一样,但是我们是可以将三道题进行一个共同的抽象的:

        给定一个数组表示股票每天的价格,在最多完成 k 次交易的情况下如何获利最多。

        此时,我们就需要换一种思路,找到一个更通用的方法。因为现在k对于我们来说是一个变量,k表示的是最多能完成的交易次数,而不是必须要完成的交易次数。所以交易1~k次的情况我们都需要考虑。

        我们定义local[i][j]为在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,此为局部最优。然后我们定义global[i][j]为在到达第i天时最多可进行j次交易的最大利润,此为全局最优。它们的递推式为:

    diff = prices[i] - prices[i - 1]

    local[i][j] = max(global[i - 1][j - 1] + max(diff, 0), local[i - 1][j] + diff)

    global[i][j] = max(local[i][j], global[i - 1][j])

        我们需要进行两级的循环,分别对应 i 与 j 。这样在完成循环后,global[len(prices)][k]就是我们所要求的值。也即股票买卖的第四题。

        本次只分享到这里,股票买卖的最后两题又加入了新的额外限定条件,如果有兴趣可以尝试解答一下。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容