Best Time to Buy and Sell Stock IV(動態規劃)

題意:有一支股票每天的價格波動,請在給定的時間內完成k次交易使收益最大,一次交易代表買入再賣出,交易不能重疊(必須賣完之後在買)。

題解:我們首先設global[i][j]爲到第i天爲止交易j次的最大收益。
因爲最後一次交易要麼在第i天賣出,要麼在之前賣出。在之前賣出的最大收益顯然是global[i-1][j],而要求第i天賣出的最大收益我們需要枚舉在前面哪一天買進。可以得到轉移方程:
global[i][j] = max{global[i-1][j], max{global[k][j-1]+p[i]-p[k], 0<=k<=i}};
以上我們將k=i單獨取出來則可以化簡爲:
global[i][j] = max{global[i-1][j], global[i][j-1], max{global[k][j-1]+p[i]-p[k], 0<=k<=i-1}};
以上爲N^2*k的複雜度。
但是我們仔細觀察最後一個max式子可以發現這個有明顯的遞推關係。它的意義在於僅在第i天賣出的最大收益。
則我們以空間換時間,再新建一個數組local[i][j]代表前i天交易j次,且第j次交易必須在第i天賣出的最大收益。
則有轉移方程:
local[i][j] = max{global[k][j-1]+p[i]-p[k], 0<=k<=i},我們將p[i]-p[k] = p[i]-p[i-1]+p[i-1]-p[k]。

local[i][j] = max{global[k][j-1]+p[i-1]-p[k], 0<=k<=i}+p[i]-p[i-1],
再進一步
local[i][j] = max{global[i][j-1], max{global[k][j-1]+p[i-1]-p[k], 0<=k<=i-1}+p[i]-p[i-1]},
其中,max{global[k][j-1]+p[i-1]-p[k], 0<=k<=i-1}就是local[i-1][j]。
則有最終的轉移方程:
local[i][j] = max{global[i][j-1], local[i-1][j]+p[i]-p[i-1]}
global[i][j] = max{global[i-1][j], local[i][j]}
具體實現時可以使用滾動數組節省空間。

代碼如下:

class Solution {
public:
    int quickSolve(vector<int>& prices) {
        int maxProfit = 0;
        for(int i = 1;i < prices.size();i++) {
            if(prices[i] > prices[i-1]) {
                maxProfit += prices[i]-prices[i-1];
            }
        }
        return maxProfit;
    }

    int maxProfit(int k, vector<int>& prices) {
        int pSize = prices.size();
        if(k >= pSize/2) {
            //相當於可以進行無限次交易
            return quickSolve(prices);
        }
        vector<int> local(k+1, 0);
        vector<int> global(k+1, 0);
        for(int i = 1;i < pSize;i++) {
            int diff = prices[i]-prices[i-1];
            for(int j = 1;j <= k;j++) {
                local[j] = max(global[j-1], local[j]+diff);
                global[j] = max(global[j], local[j]);
            }
        }
        return global[k];
    }
};
發佈了99 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章