LeetCode | Best Time to Buy and Sell Stock III(股票购买抛售问题III)

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).

题目解析:

方案一:

题目要求最多两次,要么一次要么两次。怎么去求呢?既然不一定非要两次,我们可以从i位置分开[0…i] [i…n],左边求一次,右边求一次,两次求和,当i=0或i=n的时候,求解一次。这样就满足了题意。也正是因为两次是不能重叠的,所有可以分开。而每一次求的时候,利用Best Time to Buy and Sell Stock的线性方案。要循环n次,所以时间复杂度为O(n^2)。会超时。

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int len = prices.size();
        if(len <= 1)
            return 0;
        int max = 0;
        for(int i = 0;i < len;i++){
            int sum = OneProfit(prices,0,i) + OneProfit(prices,i,len-1);
            max = max > sum ? max : sum;
        }
    }
    int OneProfit(vector<int> &prices,int begin,int end) {
        if(begin >= end)
            return 0;
        int res = 0;
        int min = prices[begin];
        for(int i = begin;i <= end;i++){
            if(prices[i] < min)
                min = prices[i];
            else{
                if(prices[i]-min > res)
                    res = prices[i]-min;
            }
        }
        return res;
    }
};

方案二:

我们从[0…i]求出最大值后,如果快速推出[0…i+1]呢?可以让函数返回一个最小值,求a[i+1]-min,再判断是否更新收益。但如何求解[i…n]推出[i+1…n]呢?这样看似不可能的,但我们反过来求,让r[i]表示r[i…n]的最大收益,而不是r[0…i]的最大收益。

将正向数组和反向数组都求出后,直接l[i]+r[i]就是我们要求的在第i个位置分割的最大收益。

这个思想很好,没有逆向思维是不容易想出来的。要加强这方面的考虑。

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int profit = 0, n = prices.size();
        if (n == 0) {
            return 0;
        }
        int l[n], r[n];
        memset(l, 0, sizeof(int) * n);
        memset(r, 0, sizeof(int) * n);
        int min = prices[0];
        for (int i = 1; i < n; i++) {
            l[i] = prices[i] - min > l[i - 1] ? prices[i] - min : l[i - 1];        
            min = prices[i] < min ? prices[i] : min;
        }
        int max = prices[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            r[i] = max - prices[i] > r[i + 1] ? max - prices[i] : r[i + 1];
            max = prices[i] > max ? prices[i] : max;
        }
        for (int i = 0; i < n; i++) {
            profit = l[i] + r[i] > profit ? l[i] + r[i] : profit;
        }
        return profit;      
    }
};

点赞