跳到主要内容

BM80. 买卖股票的最好时机(一)

题目描述​

给定数组 prices,prices[i] 是股票第 i 天的价格。 你可以买入一次、卖出一次,且买入必须在卖出之前的某一天。 求能获得的最大收益;如果不能获利,返回 0。

输入格式​

  • prices:int 型一维数组,表示每一天的股票价格。

输出格式​

返回 int 型,最大收益(不能获利则为 0)。

示例​

示例 1​

输入:

prices = [8,9,2,5,4,7,1]

输出:

5

说明: 第 3 天(价格 2)买入,第 6 天(价格 7)卖出,利润 7 - 2 = 5。

示例 2​

输入:

prices = [2,4,1]

输出:

2

说明: 第 1 天(价格 2)买入,第 2 天(价格 4)卖出,利润 2。

示例 3​

输入:

prices = [3,2,1]

输出:

0

说明: 价格单调下跌,无法获利,返回 0。


解题思路​

第一步:理解问题本质​

只能做「一次买入 + 一次卖出」,且买入在卖出之前。 等价于:找一对下标 i < j,使 prices[j] - prices[i] 最大。

第二步:暴力枚举​

枚举买入日和卖出日,取最大差价:

best = 0
for i in range(n):
for j in range(i + 1, n):
best = max(best, prices[j] - prices[i])

O(n²),思路直白但不够快。

第三步:一次遍历(贪心)​

换个角度:固定卖出日 j,那么买入日当然选「j 之前价格最低的那天」。 于是只要从左到右扫一遍,边扫边维护「到目前为止的最低价 min_price」, 就得到「今天卖出的最大利润」prices[j] - min_price,再对所有 j 取最大。

用一个变量记住最低价,就把 O(n²) 降到了 O(n)。


完整代码实现​

算法可视化 · 逐帧回放这道题的代码12 帧 · 录制输入 [8,9,2,5,4,7,1]
from typing import List


class Solution:
def maxProfit(self, prices: List[int]) -> int:
"""一次交易:维护历史最低价,更新最大利润"""
min_price = float('inf')
best = 0
for p in prices:
min_price = min(min_price, p) # 到当天为止的最低价
best = max(best, p - min_price) # 今天卖出的最大收益
return best

示例推演​

以 prices = [8,9,2,5,4,7,1] 为例:

当天价格 pmin_price今天卖出的利润 p - min_pricebest
8800
9811
2201
5233
4223
7255
1105

最终 best = 5,与答案一致。


复杂度分析​

解法时间复杂度空间复杂度说明
双重循环O(n²)O(1)简单但慢
一次遍历O(n)O(1)推荐

易错点总结​

1. 先卖出再买入​

题目要求买入在卖出之前,遍历时是「先更新 min_price,再算利润」, 不要反。

2. 忘记「不能获利返回 0」​

best 初始化成 0 就能天然处理单调下跌的情况(利润永远为负,取 0)。

3. 用「最大值 - 最小值」图省事​

直接取全局最大减全局最小是错的 —— 最大值可能出现在最小值左边, 违反了「先买后卖」。


扩展思考​


相关题目​

自测​

加载评论中...