Best Time to Buy and Sell Stock III

来源:互联网 发布:import form js 编辑:程序博客网 时间:2024/06/06 05:43
Problem:

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

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

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

思路:先找到最大的transaction fmax,再找到次大的transaction smax。然后把最大的transaction分割成获利最大的两个子transaction。如果分割的子transaction获利大于fmax+smax,则最大获利为分割的子transaction,否则为fmax+smax。算法的时间复杂度为O(n^2)。

再贴两段大神的C++代码。Solution1的时间复杂度为O(n)。Solution2更具普适性,能以O(kn)的时间复杂度解决k个transaction的问题。论文 "Maximum-Scoring Segment Sets"专门研究了这个问题。
Solution1:
public class Solution {
    public int maxProfit(int[] prices) {
       if(prices==null||prices.length==0||prices.length==1)
        return 0;
       
       int fmax=0,cost=0,fbegin=0,fend=0,smax=0,overlap=0;


       for(int i=1;i<prices.length;i++)
       {
            if(prices[i]-prices[cost]>fmax)
            {
                fbegin = cost;
                fend = i;
                fmax = prices[i] - prices[cost];
            }
            if(prices[i]<prices[cost])
            {
                cost = i;
            }
       }
       
       if(fbegin>1)
       {
            cost = 0;
            for(int i=1;i<fbegin;i++)
           {
                if(prices[i]-prices[cost]>smax)
                    smax = prices[i] - prices[cost];
                if(prices[i]<prices[cost])
                {
                    cost = i;
                }
            }
       }
       
       if(fend<prices.length-2)
       {
            cost = fend + 1;
            for(int i=fend + 2;i<prices.length;i++)
           {
                if(prices[i]-prices[cost]>smax)
                    smax = prices[i] - prices[cost];
                if(prices[i]<prices[cost])
                {
                    cost = i;
                }
            }
       }
       
       for(int i=fbegin;i<=fend;i++)
       {
            for(int j=i+1;j<=fend;j++)
            {
                if(prices[i]-prices[j]>overlap)
                    overlap = prices[i] - prices[j];
            }
        } 
       return fmax+overlap>fmax+smax?fmax+overlap:fmax+smax;
    }
}


Solution2:
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        // null check
        int len = prices.size();
        if (len==0) return 0;


        vector<int> historyProfit;
        vector<int> futureProfit;
        historyProfit.assign(len,0);
        futureProfit.assign(len,0);
        int valley = prices[0];
        int peak = prices[len-1];
        int maxProfit = 0;


        // forward, calculate max profit until this time
        for (int i = 0; i<len; ++i)
        {
            valley = min(valley,prices[i]);
            if(i>0)
            {
                historyProfit[i]=max(historyProfit[i-1],prices[i]-valley);
            }
        }


        // backward, calculate max profit from now, and the sum with history
        for (int i = len-1; i>=0; --i)
        {
            peak = max(peak, prices[i]);
            if (i<len-1)
            {
                futureProfit[i]=max(futureProfit[i+1],peak-prices[i]);
            }
            maxProfit = max(maxProfit,historyProfit[i]+futureProfit[i]);
        }
        return maxProfit;
    }
};

Solution3:
int maxProfit(vector<int> &prices) {
    vector<bool> segs(prices.size());
    int maxprofit = 0;
    for (int transact = 0; transact < 2; ++transact) {
        int i0 = 0, c = 0, cmax = 0;
        vector<int> s;
        for (int i = 0; i < (int)prices.size()-1; ++i) {
            if (i > 0 && segs[i] != segs[i-1]) {
                i0 = i; c = 0;
            }
            c = c + prices[i+1] - prices[i];
            if ((!segs[i] && c <= 0) || (segs[i] && c >= 0)) {
                i0 = i+1; c = 0;
            } else if (cmax < abs(c)) {
                cmax = abs(c); s = {i0, i};
            }
        }
        if (cmax == 0) break;
        for (int i = s[0]; i <= s[1]; ++i) segs[i] = !segs[i];
        maxprofit += cmax;
    }
    return maxprofit;
}
0 0
原创粉丝点击