给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:

输入:[7,1,5,3,6,4] **输出:**5 **解释:**在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

**输入:**prices = [7,6,4,3,1] **输出:**0 **解释:**在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

  • 1 <= prices.length <= 10^5
  • 0 <= prices[i] <= 10^4

思路

这道题在leetcode上标为简单,但实际上没那么简单。评论区很多人写的非常复杂,也引发了诸多讨论。包括我自己,循着简单的路子也没想到很好的办法。这道题有以下麻烦,

  1. 不能单纯取最大最小,因为最小必须在最大之前,才能做到低买高卖
  2. 如果最小索引大于最大索引,也不能直接判断无法收益,因为还要分析次大最小,次小最大,次大次小等等组合,又是一个 复杂度
  3. 能不能想到一种方式,在遍历一次的情况下,就能把它解决呢?

参考思路:简洁写法:枚举卖出价格,维护买入的最小值 - 灵茶山艾府

这其实是一种贪心法的体现。我每天都想着卖出,然后我记着直道今天为止的最低价格。然后记录每天尝试卖出能获得多少收益,最后取最大值即可。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        const int n = prices.size();
        if (n <= 1) return 0;
 
        int ans = 0, min_before = prices.front();
        for (int e : prices) {
	        ans = max(ans, e - min_before);
	        min_before = min(min_before, e);
        }
        return ans;
    }
};

想不到上面的思路,绝对写不出这么简洁的解答。