Hard-题目21:123. Best Time to Buy and Sell Stock 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.
题目大意:
给出一个数组,代表一个股票每一天的股价。现在你最多可以买卖两次,求出最大利益。
题目分析:
使用两个dp数组,dp1从正向扫描,其中dp1[i]表示0~i天买卖一次的最大收益,dp2从反向扫描,dp2[i]表示第i~n-1天买卖一次的最大收益。然后再并行扫一遍dp1和dp2,计算dp1[i]+dp2[i+1]的最大值。
dp1因为是正向扫的,所以维护当前子序列的最小值min,可以由dp[i-1]推出dp[i]:
dp[i]=max(dp[i-1],prices[i]-min),即如果在第i天卖了可以获得更大的收益,则在第i天卖掉,否则与在第i-1天之前卖是一样的。
同理,维护最大值max可以由dp2[i+1]推出dp2[i]:
dp2[i]=max(dp2[i+1],max-prices[i]),道理同上。
最后有的同学还会提出这样的问题:如果只买卖一次是最优的呢?
没关系,dp1[n-1]就是一次买卖的最大收益。
源码:(language:java)

public class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length<2)
            return 0;
        int[] dp1 = new int[prices.length];
        int[] dp2 = new int[prices.length];
        int min = prices[0];
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] < min)
                min = prices[i];
            dp1[i] = Math.max(dp1[i - 1], prices[i] - min);
        }
        int max = prices[prices.length - 1];
        for (int i = prices.length - 2; i >= 0; i--) {
            if (prices[i] > max)
                max = prices[i];
            dp2[i] = Math.max(dp2[i + 1], max - prices[i]);
        }
        int profit = Math.max(dp1[prices.length-1], dp2[0]);
        for (int i = 0; i < prices.length-1; i++) {
            if (dp1[i] + dp2[i+1] > profit)
                profit = dp1[i] + dp2[i+1];
        }
        return profit;
    }
}

成绩:
3ms,beats 42.07%,众数2ms,38.19%
Cmershen的碎碎念:
一开始我想到的是套用股票第1题的函数求dp1和dp2,这样需要 n2 的复杂度,提交上去超时了。然后发现dp1可以用左边项来推,dp2也可以用右边项来推。这样就降到O(n)时间复杂度了。

你可能感兴趣的:(Hard-题目21:123. Best Time to Buy and Sell Stock III)