LintCode 151 買賣股票的最佳時機 III

LintCode 151 買賣股票的最佳時機 III

今天做了兩道動態規劃的題目,感覺對動態規劃有了更深入的瞭解。廢話不多說,這是第一道。題目要求如下:

假設你有一個數組,它的第i個元素是一支給定的股票在第i天的價格。設計一個算法來找到最大的利潤。你最多可以完成兩筆交易。
注意事項
你不可以同時參與多筆交易(你必須在再次購買前出售掉之前的股票)

給出樣例如下:

給出一個樣例數組 [4,4,6,1,1,4,2,5],返回 6

題目給出的框架如下:

class Solution {
public:
    /**
     * @param prices: Given an integer array
     * @return: Maximum profit
     */
    int maxProfit(vector<int> &prices) {
        // write your code here
    }
};

解題思路

一開始的想法是用兩個數組buy[]和sell[]來解決,狀態轉移方程爲:

buy[i] = max(buy[i-1],sell[i-1] - prices[i])
sell[i] = max(sell[i-1],buy[i-1] + prices[i])

最後返回sell[len-1],其中 i 爲當前天數,len爲總共的天數。

想法很簡單,將當前狀態分爲已經買入股票和已經賣出股票這兩種:

1. 如果第 i 天的狀態爲買入股票的話, 要麼就是之前買了股票,第i天不買,對應於buy[i-1];要麼就是之前賣了股票,第i天買入股票,對應於sell[i-1] - prices[i])

2. 同理, 如果第 i天的狀態爲賣出股票的話,要麼就是之前賣了股票,第i天不賣,對應於sell[i-1];要麼就是之前買了股票,第i天賣掉,對應於buy[i-1]+ prices[i]

但這忽視了一個條件:

你最多可以完成兩筆交易!

因此,上面的狀態轉移方程解決的問題應該是 :

不管你交易多少筆,你的最大獲利是多少!

這是因爲你沒有限制交易多少筆,所以只要能獲利,我就可以將交易增加到3次,4次甚至更多次,sell[len]的值也會相應的增加。

那如何限制交易的次數爲2呢?

既然你說只能交易兩次,那麼我就對buysell兩次交易分別用兩個數組存不就行了?!說做就做,狀態轉移方程如下:

firstBuy[i] = max(firstBuy[i - 1], -prices[i])

firstSell[i] = max(firstSell[i - 1], firstBuy[i - 1] + prices[i])

secondBuy[i] = max( secondBuy[i - 1], firstSell[i - 1] - prices[i])

secondSell[i] = max( secondSell[i - 1], secondBuy[i - 1] + prices[i])

方程很好理解:

1. 如果第 i 天爲第一次買的狀態,要麼就是之前買過了,第i天不賣,對應於firstBuy[i -1],要麼就是之前沒有買,第i天買入股票,對應於-prices[i]

2. 如果第 i 天爲第一次賣的狀態,要麼就是之前賣出了,第i天不買,對應於firstSell[i -1],要麼就是之前買入了股票,第i天賣出股票,對應於firstBuy[i - 1] + prices[i]

3. 如果第 i 天爲第二次買的狀態,要麼就是之前已經二次買過了,第i天不賣,對應於secondBuy[i -1],要麼就是之前賣過一次了,第i天再次買入股票,對應於firstSell[i - 1] - prices[i]

4. 如果第 i 天爲第二次賣的狀態,要麼就是之前已經二次賣過了,第i天不買,對應於secondSell[i -1],要麼就是之前第二次購買,第i天賣出股票,對應於secondBuy[i - 1] + prices[i]

最後,還需要對第一天的買賣進行初始化:

firstBuy[0] = -prices[0]

secondBuy[0] = -prices[0]

firstSell[0] = 0

secondSell[0] = 0

代碼實現

代碼實現如下:

class Solution {
public:
    /**
     * @param prices: Given an integer array
     * @return: Maximum profit
     */
    int maxProfit(vector<int> &prices) {
        // write your code here
        const int len = prices.size();
        if (len == 0)
            return 0;
        int firstBuy[len];
        int secondBuy[len];
        int firstSell[len];
        int secondSell[len];
        firstBuy[0] = -prices[0];
        secondBuy[0] = -prices[0];
        firstSell[0] = 0;
        secondSell[0] = 0;
        for (int i = 1; i < len; ++i) {
            firstBuy[i] = max(firstBuy[i - 1], -prices[i]);
            firstSell[i] = max(firstSell[i - 1], firstBuy[i - 1] + prices[i]);
            secondBuy[i] = max(secondBuy[i - 1], firstSell[i - 1] - prices[i]);
            secondSell[i] = max(secondSell[i - 1],
                    secondBuy[i - 1] + prices[i]);
        }
        return secondSell[len - 1];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章