1. 程式人生 > >LeetCode——動態規劃——股票最大收益

LeetCode——動態規劃——股票最大收益

股票最大收益

一、問題描述

給出每天股票的價格,設計一個演算法計算出最大收益。可以最多買賣兩個回合。而且賣出之後才能再買。

二、樣例

// 1
Input : [3, 3, 5, 0, 0, 3, 1, 4]
Output : 6
Explanation : 0-3, 1-4

// 2
Input : [1, 2, 3, 4, 5]
Output : 4
Explanation : 1-5

// 3
Input : [7, 6, 4, 3, 1]
Output : 0
Explanation : 0

三、解題思路

1、我的想法

構建一個大小為 l

e n g t h ( l e n g
t h + 1 ) length *(length +1) 陣列 d p
dp
,然後 d p [ i ] [ j ] ( i [ 0 , l e n g t h ) , j [ 0 , l e n g t h ] ) dp[i][j](i\in[0, length), j\in[0, length]) 表示以價格 p r i c e s [ i ] prices[i] 買入, p r i c e s [ j ] prices[j] 賣出的收益。而 d p [ i ] [ l e g n t h ] dp[i][legnth] 表示以價格 p r i c e s [ i ] prices[i] 買入,然後以某價格賣出的最高收益。然後從每個大於零 的收益開始尋找最大收益,對於任意 d p [ i ] [ j ] dp[i][j] ,此時表示第一次交易,以 i i 價格買入, j j 價格賣出,然後在此基礎上尋找第二次的最大收益,即尋找出 m a x ( d p [ x ] [ l e n g t h ] ) , x [ j , l e n g t h ) max(dp[x][length]), x\in[j, length) t e m p M a x = d p [ i ] [ j ] + m a x ( d p [ x ] [ l e n g t h ] ) tempMax = dp[i][j] + max(dp[x][length]) ,對於每一行,都找到一個臨時最大值,最後得出最大收益。
很明顯時間複雜度 O ( n 3 ) O(n^3) ,空間複雜度 O ( n 2 ) O(n^2)

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int length = prices.size();
        vector<vector<int>> dp(length, vector<int>(length + 1, 0));
        int max = 0;
        for(int i = length - 1; i >= 0; -- i){
            for(int j = i + 1; j < length; ++ j){
                dp[i][j] = prices[j] - prices[i];
                if(dp[i][j] > max)
                    max = dp[i][j];
            }
            dp[i][length] = max;
            max = 0;
        }
        int temp;
        for(int i = 0; i < length; ++ i){         
            for(int j = i + 1; j < length; ++ j){
                if(dp[i][j] < 0)
                    continue;
                temp = dp[i][j];
                int temp_max = 0;
                for(int k = j; k < length; ++ k){
                    if(temp_max < dp[k][length])
                        temp_max = dp[k][length];
                }
                temp += temp_max;
                if(max < temp)
                    max = temp;
                
            }
        }
        return max;
    }
};

2、LeetCode童鞋答案

原連結
毫無疑問是用動態規劃,可如何能找到遞推式卻是一個永恆的問題。有時候比女盆友還難找。
d p [ i ] [ j ] dp[i][j] 表示總共進行 i i 次交易,以第 j j 天結尾時的最高收益,那遞推式
d p [ i ] [ j ] = m a x ( d p [ i ] [ j 1 ] , p r i c e s [ j ] p r i c e s [ x ] + d p [ i 1 ] [ x ] ) x [ 0 , j 1 ] d p [ i ] [ j ] = m a x ( d p [ i ] [ j 1 ] , p r i c e s [ j ] + m a x ( d p [ i 1 ] [ x ] p r i c e s [ x ] ) ) d p [ 0 ] [ j ] = 0 d p [ i ] [ 0 ] = 0 dp[i][j] = max(dp[i][j-1], prices[j] - prices[x] + dp[i-1][x]) \quad x \in [0, j-1] \newline dp[i][j] = max(dp[i][j-1], prices[j] + max(dp[i-1][x]-prices[x] )) \newline dp[0][j] = 0 \newline dp[i][0] = 0
通過一定的程式碼優化,時間複雜度和空間複雜度為 O ( k n ) , O ( k n ) O(k * n), O(k * n)

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int length = prices.size();
        if(length == 0)
            return 0;
        int k = 2, maximum = 0, tmp_max;
        vector<vector<int>> dp(k+1, vector<int>(length, 0));
        for(int i = 1; i < k+1; ++ i){
            tmp_max = dp[i-1][0] - prices[0];
            for(int j = 1; j < length; ++ j){
                dp[i][j] = max(dp[i][j-1], prices[j] + tmp_max);
                    tmp_max = max(tmp_max, dp[i-1][j] - prices[j]);
                    maximum = max(dp[i][j], maximum);
            }
        }
        return maximum;
        
    }
};