4 Best Time to Buy and Sell Stock III_Leetcode

Say you have an array for which the ith element is the price of a given stock on day i.html

Design an algorithm to find the maximum profit. You may complete at most two transactions.spa

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again)..net

當遇到限制次數以及求最大的要求時,很天然要聯想到動規。設計

動規中不一樣的狀態設計,會有不一樣的時間複雜度。code

本題有兩種解法:htm

(1) blog

我最開始想到的是下面這種解法,可是Memory Limit Exceeced.ip

O(n^2)的解法element

很天然的咱們會想到記錄從開頭到第i個字符中進行k次交易可以獲得的最大收益,記爲dp[i][k].leetcode

進行更新:dp[i][k] = max{dp[j][k-1]+maxprofit(j...i)}, 0 <= j < i

這裏咱們須要用到每一個可能的區間中進行一次交易的最大收益,也就是I中的問題。

預先計算出全部的maxprofit的複雜度是O(n^2),dp的複雜度也是O(n^2).

Code:

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int n = prices.size();
        if(n == 0) return 0;
        vector<vector<int>> dp(n, vector<int>(3,0));
        vector<vector<int>> maxprofit(n, vector<int>(n, 0));
        
        for(int i = 0; i < n; i++)
        {
            int curmin = prices[i];
            int curprofit = 0;
            for(int j = i+1; j < n; j++)
            {
                if(prices[j] < curmin) curmin = prices[j];
                else{
                    int gap = prices[j] - curmin;
                    if(gap > curprofit) curprofit = gap;
                }
                maxprofit[i][j] = curprofit;
                if(i == 0) dp[j][1] = curprofit;
            }
        }
        
        for(int i = 1; i < n; i++)
        {
            int tmp = dp[0][1] + maxprofit[0][i];
            for(int j = 1; j < i; j++)
            {
                if(dp[j][1] + maxprofit[j][i] > tmp) tmp = dp[j][1]+maxprofit[j][i];
            }
            dp[i][2] = tmp;
        }
        
        return dp[n-1][2];
    }
};

 (2)O(n)的解法

參考了這個:http://blog.csdn.net/linhuanmars/article/details/23236995

從上面的分析中咱們很容易找出一個case, 例若有一個區間差別特別大,在很長時間內都是最優的選擇,而咱們的dp卻須要不斷的枚舉一些不可能構成最終解的區間。

怎麼樣更聰明的定義狀態呢?

上一種定義中,咱們是定義(i,j)中的最大的解,這樣不一樣的(i,j)對對應的多是同一種解;這樣咱們能夠用一個global變量來存儲;可是因爲處理的區間是不斷延伸的,後面出現的數字可能和當前末尾的組合起來行程更大的區間,所以咱們用一個local變量存儲當前以i結尾的最大的解的值。

擴展到可以選擇k個區間,咱們定義:

global(i,k) 表示截止到第i天,進行k次交易可以得到的最優解(不必定以最後一天結束)

local(i,k) 表示以第i天結束的k次交易可以得到的最優解

可以獲得遞推式:

local[i][k] = max{global[i-1][k-1], local[i-1][k]} + prices[i] - prices[i-1];

global[i][k] = max{global[i-1][k], local[i][k]};

初始值全爲零,最終解爲global[n-1][2]。

Code:

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int n = prices.size();
        if(n == 0) return 0;
        vector<vector<int>> global(n, vector<int>(3,0));
        vector<vector<int>> local(n, vector<int>(3,0));
        
        for(int j = 1; j <= 2; j++)
        {
            for(int i = 1; i < n; i++)
            {
                local[i][j] = max(global[i-1][j-1], local[i-1][j]) + prices[i] - prices[i-1];
                global[i][j] = max(global[i-1][j], local[i][j]);
            }
        }
        return global[n-1][2];
    }
};

 

從其餘博客中找到了一種O(n)的解法,思路更簡單,可是不具有從2次交易推廣到k次的潛力。

主要的思路就是從前日後掃描一遍,找到從0到i的一次交易的最大收益,而後從後往前掃描一遍,獲得從i+1到n-1的最大收益。而後二者相加取最大便可。

傳送門:http://fisherlei.blogspot.com/2013/01/leetcode-best-time-to-buy-and-sell_3958.html

相關文章
相關標籤/搜索