動態規劃-股票買賣總結

轉載自:http://liangjiabin.com/blog/2015/04/leetcode-best-time-to-buy-and-sell-stock.html

Best Time to Buy and Sell Stock I

Description: Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find
the maximum profit.

題意:用一個數組表示股票每天的價格,數組的第i個數表示股票在第i天的價格。 如果只允許進行一次交易,也就是說只允許買一支股票並賣掉,求最大的收益。

分析:動態規劃法。從前向後遍歷數組,記錄當前出現過的最低價格,作爲買入價格,並計算以當天價格出售的收益,作爲可能的最大收益,整個遍歷過程中,出現過的最大收益就是所求。

代碼:O(n)時間,O(1)空間。


Best Time to Buy and Sell Stock II

Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

題目:用一個數組表示股票每天的價格,數組的第i個數表示股票在第i天的價格。交易次數不限,但一次只能交易一支股票,也就是說手上最多隻能持有一支股票,求最大收益。

分析:貪心法。從前向後遍歷數組,只要當天的價格高於前一天的價格,就算入收益。

代碼:時間O(n),空間O(1)。


Best Time to Buy and Sell Stock III

Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

題意:用一個數組表示股票每天的價格,數組的第i個數表示股票在第i天的價格。最多交易兩次,手上最多隻能持有一支股票,求最大收益。

分析:動態規劃法。以第i天爲分界線,計算第i天之前進行一次交易的最大收益preProfit[i],和第i天之後進行一次交易的最大收益postProfit[i],最後遍歷一遍,max{preProfit[i] + postProfit[i]} (0≤i≤n-1)就是最大收益。第i天之前和第i天之後進行一次的最大收益求法同Best Time to Buy and Sell Stock I。

代碼:時間O(n),空間O(n)。


Best Time to Buy and Sell Stock IV

Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most k transactions. Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

題意:用一個數組表示股票每天的價格,數組的第i個數表示股票在第i天的價格。最多交易k次,手上最多隻能持有一支股票,求最大收益。

分析:特殊動態規劃法。傳統的動態規劃我們會這樣想,到第i天時進行j次交易的最大收益,要麼等於到第i-1天時進行j次交易的最大收益(第i天價格低於第i-1天的價格),要麼等於到第i-1天時進行j-1次交易,然後第i天進行一次交易(第i天價格高於第i-1天價格時)。於是得到動規方程如下(其中diff = prices[i] – prices[i – 1]):

profit[i][j] = max(profit[i – 1][j], profit[i – 1][j – 1] + diff)

看起來很有道理,但其實不對,爲什麼不對呢?因爲diff是第i天和第i-1天的差額收益,如果第i-1天當天本身也有交易呢(也就是說第i-1天剛賣出了股票,然後又買入等到第i天再賣出),那麼這兩次交易就可以合爲一次交易,這樣profit[i – 1][j – 1] + diff實際上只進行了j-1次交易,而不是最多可以的j次,這樣得到的最大收益就小了。

那麼怎樣計算第i天進行交易的情況的最大收益,纔會避免少計算一次交易呢?我們用一個局部最優解和全局最有解表示到第i天進行j次的收益,這就是該動態規劃的特殊之處。

用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] , local[i – 1][j] + diff)
global[i][j] = max(global[i – 1][j], local[i][j])

local[i][j]和global[i][j]的區別是:local[i][j]意味着在第i天一定有交易(賣出)發生,當第i天的價格高於第i-1天(即diff > 0)時,那麼可以把這次交易(第i-1天買入第i天賣出)跟第i-1天的交易(賣出)合併爲一次交易,即local[i][j]=local[i-1][j]+diff;當第i天的價格不高於第i-1天(即diff<=0)時,那麼local[i][j]=global[i-1][j-1]+diff,而由於diff<=0,所以可寫成local[i][j]=global[i-1][j-1]。global[i][j]就是我們所求的前i天最多進行k次交易的最大收益,可分爲兩種情況:如果第i天沒有交易(賣出),那麼global[i][j]=global[i-1][j];如果第i天有交易(賣出),那麼global[i][j]=local[i][j]。

參考:http://www.cnblogs.com/grandyang/p/4295761.html

代碼:時間O(nk),空間O(nk)。

我們知道,動規所用的二維輔助數組可以降爲一維的,即只用大小爲k的一維數組記錄到達第i天時的局部最優解和全局最優解。需要注意的是,由於第i天時交易k次的最優解依賴於第i-1天時交易k-1次的最優解,所以數組更新應當從後往前(即從k到1)更新。

代碼:時間O(nk),空間O(k)。

補充:這道題還有一個陷阱,就是當k大於天數時,其實就退化成 Best Time to Buy and Sell Stock II 了。就不能用動規來做了,爲什麼?(請思考) 另外,Best Time to Buy and Sell Stock III 就是本題k=2的情況,所以說IV是II和III的綜合。

(完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章