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

Say you have an array for which the i^{th} 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的情况。具体就不再详述啦~

 

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

在求解部分最低值和部分最高值的差值的过程,其实就是将从部分最低值到部分最高值过程中的多天的差值相加,也就是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提问”按钮问我问题,我将竭力解答你的疑惑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值