leetcode-188 買賣股票4


題目

    給定一個數組表示股票每天的價格,最多交易k次,且手上最多只能擁有一支股票(即只能先賣出手上現有的股票再去購買新的股票),求最大的收益。 
    題目鏈接:買賣股票4 
    開始思路不清楚,參考了http://blog.csdn.net/dr_unknown/article/details/51939121 的解法。 
使用動態規划,先找清狀態,題目中有兩個主要變量天數,和交易次數,以及所要求的結果:最大的收益。那么可以構造狀態dp[i][j],表示前i天最多交易j次獲得的最大收益。 
    有了狀態dp,可以找到遞推公式:dp[i][j] = max{dp[i-1][j], dp[i-1][j-1] + prices[i] - prices[i-1]}:前i天進行j次的最大收益,等於前i-1天進行完最多j次交易的收益A和前i-1天進行完j-1次交易,且第i天進行最后一次交易的收益B的最大值。 
    但是這樣有個問題,對於第二種情況,如果dp[i-1][j-1]中第j-1次交易是在第i-1天進行了賣出,那么 dp[i-1][j-1] + prices[i] - prices[i-1] 就相當於第j-1次交易是在第i天進行了賣出,最終相當於i天最多只進行了j-1次交易。 
    於是,需要細化狀態,考慮使用狀態 local[i][j]表示前i天最多進行j次交易,且最后一次賣出交易是在第i天完成,所獲得的最大收益;global[i][j]表示前i天最多進行j次交易所獲得的最大收益。 
於是有遞歸公式: 
local[i][j] = max{global[i-1][j-1] + max(prices[i] - prices[i-1], 0), local[i-1][j] + prices[i] - prices[i-1]} 
global[i][j] = max{local[i][j], global[i-1][j]}
 
    進一步的,狀態第一維i只和i-1有關,可以進行空間壓縮,將二維數組變成一維,於是有遞推公式: 
local[j] = max{global[j-1] + max(prices[i] - prices[i-1], 0), local[j] + prices[i] - prices[i-1]} 
global[j] = max{local[j], global[j]}
 
但是需要注意j需要從高到低遍歷,因為第i天交易j次的最優解依賴於第i-1天交易j-1次的最優解。 
    進行狀態壓縮時,數組的遍歷方向很容易搞混,這是可以使用滾動數組,滾動數組一方面可以壓縮空間,另一方面也不需要太過考慮數組的遍歷方向。 
local[new_scroll][j] = max(global[old_scroll][j-1] + max(diff, 0), local[old_scroll][j] + diff); 
global[new_scroll][j] = max(local[new_scroll][j], global[old_scroll][j]);

實現

class Solution {
public:
	int maxProfit(int k, vector<int> &prices) {
	    int n = prices.size();
	    if(n <= 1)
	        return 0;
	    if(k >= n)
	        return maxProfit2(prices);
	    for(int i = 0; i < 2; i ++){
	        local[i].assign(k + 1, 0);
	        global[i].assign(k + 1, 0);
	    }
	    int old_scroll = 0, new_scroll;
	    for(int i = 1; i < n; i ++){
	        int diff = prices[i] - prices[i-1];
	        new_scroll = 1 - old_scroll;
	        for(int j = 1; j <= k; j ++){
	            local[new_scroll][j] = max(global[old_scroll][j-1] + max(diff, 0), local[old_scroll][j] + diff);
	            global[new_scroll][j] = max(local[new_scroll][j], global[old_scroll][j]); //注意這里 local 為new_scroll
	        }
	        old_scroll = new_scroll;
	    }
	    return global[new_scroll][k];
	}
	int maxProfit2(vector<int>& prices){
	    int result = 0;
	    int n = prices.size();
	    for(int i = 1; i < n; i ++){
	        if(prices[i] > prices[i-1])
	            result += (prices[i] - prices[i-1]);
	    }
	    return result;
	}
private:
    vector<int> local[2];
    vector<int> global[2];
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM