题目描述

✅ 剑指 Offer 63. 股票的最大利润

image-20261001230752594

image-20260928184508944

题意分析

数组按时间先后记录股价,最多选择一天买入,再选择更晚的一天卖出,利润是卖出价减买入价。只允许这一笔交易;没有盈利机会时可以不交易,答案为 0。

解法:一次扫描维护最低买入价

核心思路

[!blue]

如果固定第 i 天卖出,卖出价就已经确定,要让 prices[i]-买入价 最大,只需选取前 i 天中的最低价格。更贵的历史买入价不会对当前或任何未来卖出日更有利,因此不必保留所有买入候选。

用 minPrice 保存 prices[0..i-1] 的最低价,用 ans 保存此前所有卖出日能够取得的最大利润。处理第 i 天时,先以 prices[i]-minPrice 更新答案,再把当天价格纳入最低价,为下一个卖出日准备状态。

这样每个卖出日都与它之前最优的买入日配对,所有合法交易都会被相同卖出日的候选覆盖;在这些候选中取最大值,就是全局最优利润。ans 初始为 0,亏损候选不会替换“不交易”的选择。

解题步骤

  • 少于两天时无法完成先买后卖,直接返回 0,也避免读取空数组首项。
  • 初始化 minPrice = prices[0]、ans = 0,从第二天开始扫描。
  • 用 prices[i]-minPrice 更新 ans,此时最低价只来自更早的日期。
  • 用 prices[i] 更新 minPrice,扫描结束后返回 ans。

价格一直下降时,每天的候选利润都为负;价格不变时,候选利润为 0,两种情况都返回 0。后来出现更低的买入价只会改善未来候选,不会抹去已经记录的历史最高利润。

代码实现

class Solution {
    public int maxProfit(int[] prices) {
        if (prices.length < 2) {
            return 0;
        }

        int minPrice = prices[0];
        int ans = 0;

        for (int i = 1; i < prices.length; i++) {
            // 先以历史最低价尝试卖出,再把当天价格提供给未来
            ans = Math.max(ans, prices[i] - minPrice);
            minPrice = Math.min(minPrice, prices[i]);
        }

        return ans;
    }
}
func maxProfit(prices []int) int {
    if len(prices) < 2 {
        return 0
    }

    minPrice := prices[0]
    ans := 0
    for i := 1; i < len(prices); i++ {
        // 先以历史最低价尝试卖出,再把当天价格提供给未来
        if prices[i]-minPrice > ans {
            ans = prices[i] - minPrice
        }
        if prices[i] < minPrice {
            minPrice = prices[i]
        }
    }
    return ans
}

复杂度分析

  • 时间复杂度:$O(n)$,每天一次。
  • 空间复杂度:$O(1)$,最低价与最优利润。

关键点总结

[!green]

  • 历史最低与全局最低不同,未来低价不能用于此前卖出。
  • minPrice 维护未来交易的买入候选,ans 维护已经完成的最优交易,两个状态各有用途。
  • 一次交易只对应一个买卖差值,不能累加多个上涨段的收益。

易错点总结

[!yellow]

  • 直接用全局最大减最小,可能让买入晚于卖出。
  • 最低价初值零会虚构免费买入。
  • 读取首项前未处理空输入,会越界。

相似题目

题目 难度 关联与区别
122. 买卖股票的最佳时机 II 中等 本题只能完成一次交易,原题允许多次交易,可以累积不同上涨段。
123. 买卖股票的最佳时机 III 困难 把一次交易扩展为最多两次,需要分别保存每次买入卖出状态。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/75186789
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!