SWE · Onsite Coding

Apple 股票一次买卖:前缀最低价与最大收益

把买入先于卖出写成扫描不变量,处理下降行情、空数组与最多一次交易。

题目重点:把买入先于卖出写成扫描不变量,处理下降行情、空数组与最多一次交易。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练版给每天非负整数价格列表,最多买一次、卖一次,卖日严格晚于买日;可以不交易,因此最大收益至少为 0。
  • 如果原题要求恰好交易一次、存在手续费/冷却期或多笔交易,状态和答案会改变,不能直接套本函数。

解题路线

  1. 从左到右维护已经见过日期的最低价格 minimum;到新日期时,用当前价卖出能得到 `price-minimum`,先更新最大收益再把当前价纳入未来最低价。
  2. 归纳不变量:处理日期 j 后,minimum 是前 j+1 天的最低价,best 是所有买日早于卖日且卖日不晚于 j 的最大非负收益。
  3. 若行情一直下跌,每天候选收益均不正,返回 0 表示不交易。
  4. 用独立的所有 `(buy,sell)` 日期对穷举核验 21,845 条短价格序列,覆盖重复价、单日与空输入。

手动走一遍

[7,1,5,3,6,4]:最低价先降为 1,见 5 候选 4,见 6 候选 5,最终返回 5。若价格为 [7,6,4],所有合法买卖都是亏损,训练版返回 0。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def max_profit_once(prices: list[int]) -> int:
    """One buy then one later sell; at most one trade; no negative profit."""
    if not prices:
        return 0
    minimum = prices[0]
    best = 0
    for price in prices[1:]:
        best = max(best, price - minimum)
        minimum = min(minimum, price)
    return best

复杂度

单遍 O(n) 时间、O(1) 额外空间;若必须同时返回买卖日期,可额外保存最低价日期和最佳日期对,仍是 O(1) 空间。

易错点与追问

容易失分的边界

  • 卖日可早于买日,错误地用全局最小价减全局最大价。
  • 强制交易与最多一次交易的空/下降行情口径混淆。
  • 先更新最低价再把同一天视为买卖,若要求严格晚于买日需在解释中避免。
  • 把一次交易解法套到多交易或含手续费版本。

继续深挖

  • 若必须完成一次交易,下降行情返回什么?
  • 若要返回买卖日期且多组同利润怎样打破平局?
  • 两笔交易如何用状态机或前后缀 DP 处理?
  • 实时流价格到来时能否只存 O(1) 状态?
✓已复制微信号!