【算法分析與設計】【第一週】121.&122. Best Time to Buy and Sell Stock I&II

原題來自:121:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/

122:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/

第一週,小試牛刀吧。

題目121不復雜,就是英文原題讀起來怪怪的。意思是,在保證先買後賣且最多隻能買賣一次的情況下,計算最大利潤。

思路很簡單:逐個求差,差最大且被減數的下標大於減數的下標就可以了。最簡單暴力的方法是用兩重循環:

int maxProfit(int* prices, int pricesSize) {
    int max = 0;
    for (int i = 0; i < pricesSize; i++) {
        for (int j = i; j < pricesSize; j++) {
            if (prices[j] - prices[i] > max) {
                max = prices[j] - prices[i];
            }
    	}
    }
    return max;
}

顯然,此算法的時間複雜度爲0(n^2)。根據leetcode給出的分析圖,雖然AC,我的方法還有很大的優化空間。

優化的話,思路本質上還是一樣的。就是求一個峯值和谷底值之差,且峯值在谷底值後面。主要是能否想到一個巧妙的方法避開雙重循環,目前還沒想好。

 --------------------------------------------------

做完121,發現還有升級版122。122的意思是,在保證先買後賣且在一個買賣週期內最多隻能買賣一次的情況下,計算最大利潤。也就是說,賣出之後還可以再進行買入等操作。

這就很有意思了。在沒有買賣次數限制的情況下,同樣是獲得最大利潤,情況可以有多種。一開始我是懵的。第一反應是窮舉,計算出所有能盈利的情況,再進行比較,得到最大利潤。先不說這是個比較浩大的工程量,最重要的是我根本不知道這看似簡單的方法從何下手(ˉ▽ˉ;)...。

後來觀摩了一下討論區,發現一位大牛的做法很有意思。大牛的思路很巧妙,就是逐個相減,差大於零就盈利,把盈利的部分加起來;差小於零就進入往後挪,繼續相減。哇,簡直神奇!把n天切割成n次買賣,每次在第i天買入,第i+1天賣出。只看上升的小段,疊加,忽略下降的小段。

舉個簡單的例子。對於一種情況{4, 1, 2, 3, 5}來說,最佳盈利策略應當是在1的時候買入,5的時候賣出,盈利爲4,一手買賣即可。而按照上面的方法,將這一手買賣分解爲1買2賣,2買3賣,3買5賣,共盈利4,三次買賣利潤與前面的一手買賣利潤一致,但是解釋起來更加簡便、清晰。

對於另一種情況{4, 1, 3, 2, 5}來說,兩個峯,只看上升的小段,看起來就更加清楚了。

這種方法就相當於把長線買賣都簡化成了“如果保證盈利,買了馬上就賣”的小短線模式的疊加,與週五剛剛學過的“分治”思想還真有異曲同工之妙。

代碼實現起來就很簡單了:

int maxProfit(int* prices, int pricesSize) {
    int total = 0;
    for (int i=0; i< pricesSize-1; i++) {
        if (prices[i+1] > prices[i]) total += prices[i+1] - prices[i];
    }
    return total;
}




發佈了29 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章