Skip to content

Latest commit

 

History

History
 
 

122. Best Time to Buy and Sell Stock III

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

这个问题都出到 III 了,真是无穷无尽啊。参考 [Best Time to Buy and Sell Stock II](../005. Best Time to Buy and Sell Stock II) 与 [Best Time to Buy and Sell Stock](../039. Best Time to Buy and Sell Stock).

这道题从 I 里要求的仅有一次交易,转变为最多可以进行两次交易。那么很自然地,我们还是从一次交易的思路着手。

      6 1 3 2 4 7 6 10 15
 low: 6 1 1 1 1 1 1  1  1
 ret: 0 0 2 2 3 6 6  9 14
                        ^

查看一下 I 中的思路,我们运用了两个变量来完成此事,low 时刻记录最低股价,ret 则不断刷新差价,前者求 min, 后者求 max. 想在反思这种解法,实际上是非常朴素的 DP, 也是一种积累思想的体现。

如果再给我们一次机会,再来一次交易呢?就看上述例子,我们一眼就瞧出了两次交易转手的地方:

      6 1 3 2 4 7 6 10 15
 low: 6 1 1 1 1 1 1  1  1
 ret: 0 0 2 2 3 6 6  9 14
                ^ ^
                6+9 = 15 ---> ret

如果在 7 的时候卖,6 的时候买,那么竟然可以得到 15 的差价。反思一下,我们人脑是如何判别出这个点的。显然,我们可以发现,在 1~15 这个序列里,出现下降趋势的地方仅有两处:3->2, 7->6, 前者我们最终获得的差价也是 15(2+13)。而想要获得最大的差价,需这种下降的地方,下降的更多才是。这里 3-2 == 7-6 == 1. 所以第二次交易至多也只能增加 1.

在 I 里,我们采用了 low + ret 来捕获上升趋势时的变化。而根据上述分析,我们显然还对下降趋势的地方感兴趣。但这个下降有个条件,即一定要是在总的上升趋势中的小下降。那么从头开始捕获就不太合理,从尾部开始,或许可以。相似的,我们采用 high + ret 来计算。

       6  1  3  2  4  7  6 10 15
 ret:  0  0  2  2  3  6  6  9 14
      15 15 15 15 15 15 15 15 15 :high
      15 15 15 15 15 15 15 14 14 :new_ret

highlow 一样,始终记录最高股价,new_ret 则不断刷新差价。此时的 new_ret == ret + high - today. 显然,这一次两者都是求 max 了。

还可以发现的是,上一次迭代每一次 ret 都是对我们这一次的逆向迭代有用的,所以我们最终还是需要 O(n) 的缓存空间。

总结一下,两次迭代,用 vector 记录历史差价。最终得到的 ret 即为所求。AC.