leetcode题解-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.

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

延续前面两道题目,本题是只可以进行两次交易,首先想到的是先求出第一次交易的最大利润,然后再进行第二次交易,两次交易之间不能重叠。所以我们使用一个数组保存第一次遍历时每一步的最大利润,然后再进行反向遍历,找出第二次交易的利润。代码入下:

    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len < 2)
            return 0;
        int [] maxBefore = new int[len];
        int min = prices[0];
        for(int i=1; i<len; i++){
            maxBefore[i] = Math.max(maxBefore[i-1], prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        int max = prices[len - 1];
        int ret = 0;
        for(int i=len-2; i>=0; i--){
            //找到后面最大的价格
            max = Math.max(prices[i], max);
            //利润 = 最大价格 - 当前价格 + 此时交易时第一次的利润
            //取最大值
            ret = Math.max(ret, max - prices[i] + maxBefore[i]);
        }
        return ret;
    }

这种方法因为使用了两次循环,所以耗时较长,击败了18%的用户,而且使用了额外的O(n)存储空间。接下来我们需要改进算法,在看完discuss之后有了改进思路,基本想法是使用四个变量来表示第一次买入,第一次卖出,第二次买入,第二次卖出。然后再遍历的同时对其进行更新。代码入下:

public int maxProfit(int[] prices) {
    int len = prices.length;
    if(len <= 1) return 0;
    int a, b, c, d;
    //d表示从后向前遍历的最大值,c表示第一次交易之后的最大利润,b表示第二次交易之前的最大值,a表示第二次交易之后的利润之和。
    d = Math.max(prices[len-1], prices[len-2]);
    c = Math.max(prices[len-1] - prices[len-2], 0);
    b = d;
    a = c;
    for(int i=len-3; i>=0; i--) {
        //这里结合上面每个变量的意义进行理解,为什么每个变量更新的公式如下。
        a = Math.max(b - prices[i], a);
        b = Math.max(prices[i] + c, b);
        c = Math.max(d - prices[i], c);
        d = Math.max(prices[i], d);
    }
    return a;
}

这种方法可以击败58%的用户,还有另外一种解法,思路同上,如下所示,可以击败76%的用户:

public int maxProfit(int[] prices) {
    // these four variables represent your profit after executing corresponding transaction
    // in the beginning, your profit is 0. 
    // when you buy a stock ,the profit will be deducted of the price of stock.
    int firstBuy = Integer.MIN_VALUE, firstSell = 0;
    int secondBuy = Integer.MIN_VALUE, secondSell = 0;

    for (int curPrice : prices) {
        if (firstBuy < -curPrice) firstBuy = -curPrice; // the max profit after you buy first stock
        if (firstSell < firstBuy + curPrice) firstSell = firstBuy + curPrice; // the max profit after you sell it
        if (secondBuy < firstSell - curPrice) secondBuy = firstSell - curPrice; // the max profit after you buy the second stock
        if (secondSell < secondBuy + curPrice) secondSell = secondBuy + curPrice; // the max profit after you sell the second stock
    }

    return secondSell; // secondSell will be the max profit after passing the prices
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值