LeetCode 122——Best Time to Buy and Sell Stock II

Say you have an array for which the LeetCode 122——Best Time to Buy and Sell Stock II element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

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

Example 1:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
  Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
  Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
  engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

 


 

一个股票求最大收益的问题。

我们平时买股票的时候只有一个心理,那就是买的时候期望是这段时间的最低价,买完之后希望它能天天涨停,然后在最高价的时候将其卖出,就可以获得最大的收益。当然现实中一般不会发生这种情况,但是我们可以在题目中过把瘾啊~

先说下我的思路:

开始时根据索引为0和1的数字判断当前走势是增是减,然后开始循环。

在递减的时候如果发现prices[i] > prices[i - 1]成立,那就证明走势从递减变为递增了,记录此时的值为min。

在递增的时候如果发现prices[i] < prices[i - 1]成立,那就证明走势从递增变为递减了,此时的prices[i - 1]就是区域的最大值,令总收益 + prices[i - 1] - min。循环体代码如下:

if (isDown) {
    if (prices[i] > prices[i - 1]) {
        min = prices[i - 1];
        isDown = false;
    }
} else {
    if (prices[i] < prices[i - 1]) {
        totalProfit += prices[i - 1] - min;
        isDown = true;
    }
}

此时还会存在一种特殊情况,就是一直递增的时候到达了数组的末尾,没有将最后一个值与min的差值增加到总收益上去。所以要记得处理这种情况。

但是在后边放出的代码中可以看出,还是要处理prices.length < 2的情况,所以显得代码不够流畅。

 

这个思路还有另一种编码方式,代码如下:

while (i < arrLen - 1) {
    while (i < arrLen - 1 && prices[i] > prices[i + 1]) {
        ++i;
    }
    int min = prices[i];
    while (i < arrLen - 1 && prices[i] < prices[i + 1]) {
        ++i;
    }
    result += prices[i] - min;
}

很直接,一次求局部最低值,一次求局部最大值。并且代码比较清晰,不用考虑prices.length < 2的情况。具体就不再详述啦~

 

还有一个最佳思路,就是要打破思维定势,不必按照不能在同一天购买和出售去求解,首先看下图:

LeetCode 122——Best Time to Buy and Sell Stock II

在求解部分最低值和部分最高值的差值的过程,其实就是将从部分最低值到部分最高值过程中的多天的差值相加,也就是A + B + C = D,所以循环体的代码将变得十分简洁:

if (prices[i - 1] < prices[i]) {
    result += prices[i] - prices[i - 1];
}

 

当我看到这个代码的时候,只能感叹一句:路漫漫其修远兮,吾将上下而求索。

 


 

最佳代码:

class Solution {
    public int maxProfit(int[] prices) {
        int arrLen = prices.length;
        int result = 0;
        for (int i = 1; i < arrLen; ++i) {
            if (prices[i - 1] < prices[i]) {
                result += prices[i] - prices[i - 1];
            }
        }

        return result;
    }
}

 

我的AC代码:

class Solution {
    public int maxProfit(int[] prices) {
        int arrLen = prices.length;
        if (arrLen < 2) {
            return 0;
        } else {
            boolean isDown = prices[0] > prices[1];
            int totalProfit = 0;
            int min = isDown ? 0 : prices[0];

            for (int i = 1; i < arrLen; ++i) {
                if (isDown) {
                    if (prices[i] > prices[i - 1]) {
                        min = prices[i - 1];
                        isDown = false;
                    }
                } else {
                    if (prices[i] < prices[i - 1]) {
                        totalProfit += prices[i - 1] - min;
                        isDown = true;
                    }
                }
            }
            if (!isDown) {
                totalProfit += prices[arrLen - 1] - min;
            }

            return totalProfit;
    }
}

 


如有错误,欢迎指摘。也欢迎通过左上角的“向TA提问”按钮问我问题,我将竭力解答你的疑惑。