Leet123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III)

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/description/

public int maxProfit(int[] prices) 
    {
        if(prices.length==0)
        {
            return 0;
        }
        int left[]=new int[prices.length];
        int right[]=new int[prices.length];
        left[0]=0;
        right[prices.length-1]=0;
        int leftmin=prices[0];//记录左边的最小值
        for(int i=1;iprices[i-1])
            {
                left[i]=Math.max(prices[i]-leftmin, left[i-1]);
            }
            else
            {
                left[i]=left[i-1];
                leftmin=Math.min(leftmin, prices[i]);
            }
        }
        //右
        right[prices.length-1]=0;
        int rightmax=prices[prices.length-1];//记录右边最大值
        for(int i=prices.length-2;i>=0;i--)
        {
            if(prices[i+1]>prices[i])
            {
                right[i]=Math.max(rightmax-prices[i], right[i+1]);
            }
            else
            {
                right[i]=right[i+1];
                rightmax=Math.max(prices[i], rightmax);
            }
        }
        int res=0;
        for(int i=0;ires)
            {
                res=left[i]+right[i];
            }
        }
        return res;
    }

思路:

与该系列前两题不同   本题要求最多进行“两次”交易

利用动态规划处理

首先最多进行两次交易 可以将prices分为两部分 左边代表一次交易 右边代表第二次交易 而分割的位置是不确定的

但无论分割的位置是哪一处  左边、右边都将成为唯一的   那么只需要计算在每一种分割的情况下  左、右收益之和最大的是哪一种分割就可以了

用题目给出的[3,3,5,0,0,3,1,4]这组数据来还原一下计算步骤

用数组left[]表示左边的“最大收益”

用数组right[]表示右边的“最大收益”

用leftmin表示“目前左边的最低价格”  用rightmax表示“目前右边的最高价格”  为什么这样下面会解释

从left数组的计算开始

对于题目中的  3,3,5,0,0,3,1,4

将leftmin设初值为3  表示第一天买入

之后对题目数据进行遍历

从第二天开始(第一天无论是否买入,都不能卖出,所以没有收益,这时候同时设定left[0]为0)

第二天的价格为3,这个价格并没有高于上一天 (即第一天)的价格

那么此时left[1]  即第二天的最大收益也为0

然后对比第二天的价格与leftmin 相同 那么leftmin保持不变 为3

之后第三天

第三天时价格为5,高于上一天(即第二天)的价格3,若卖出 则收益2 将收益2与之前的最大收益left[1]对比 大于left[1]的0

所以将left[2]设置为2

这里解释一下:此时假定的日期分割为前三天进行第一次交易 后面进行第二次交易

而前三天中的收益分别为0  0  2  意味着 若分割在第一天 则不能买入卖出 收益为0 若分割在第二天 价格为3 3 收益仍为0 分割在第三天 则就是刚才的计算结果  所以left[i]表示的是前i天可以获得的最大收入

接下来继续推进日期

第四天时价格为0 收益仍保持前三天的最大值2  但是此时价格0低于目前的“最低价格” 故将最低价格改为0

第五天不变 略过

第六天时价格为3 此时由于最低价格为0 那么最大收益变为3

按照这样的推理方式结束时

对应日期价格 3,3,5,0,0,3,1,4的

左边最大收益 0,0,2,2,2,3,3,3

用同样的思维方式对右边进行推理 来获得right[]数组 不过由于方式是从右往左 

所以需要略作修改 因为从左往右时的默认顺序是买入-卖出 而从右往左是先卖出再买入

这也就是为什么leftmin表示“目前左边的最低价格”  用rightmax表示“目前右边的最高价格”

结束时right数组为4,4,4,4,4,3,3,0

left为:                 0,0,2,2,2,3,3,3

之后只需要看哪一组left和right之和最大即可

你可能感兴趣的:(Java,算法与数据结构)