跳到主要内容

BM81. 买卖股票的最好时机(二)

题目描述​

给定数组 prices,prices[i] 是某只股票第 i 天的价格。 你可以多次买卖该股票,但再次购买前必须卖出之前的股票(同一时刻最多持有一股)。 求最大收益;不能获取收益则返回 0。

输入格式​

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

输出格式​

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

示例​

示例 1​

输入:

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

输出:

7

说明: 第 1 天买第 2 天卖(+1)、第 3 天买第 4 天卖(+3)、 第 5 天买第 6 天卖(+3),合计 7。

示例 2​

输入:

prices = [5,4,3,2,1]

输出:

0

说明: 价格持续下跌,不交易最优。

示例 3​

输入:

prices = [1,2,3,4,5]

输出:

4

说明: 第 1 天买、最后一天卖,收益 4;中间当天买当天卖不影响结果。


解题思路​

第一步:理解问题本质​

可以交易任意多次,但同一时刻只能持有一股。 直觉上「逢低买入、逢高卖出」就能赚到每一段上涨。

第二步:为什么「逐日累加正差价」是对的​

考虑从第 i 天持有到第 j 天卖出,收益是 prices[j] - prices[i]。 这个差值恰好等于这段时间里所有相邻两天正差价之和:

prices[j] - prices[i] = Σ (prices[k+1] - prices[k])

因此,只要我们把每对相邻两天的「正差价」全部累加,就不会漏掉任何利润; 负差价则直接跳过(相当于空仓观望)。这本质上把每一段上涨都完整拿下了。

第三步:贪心实现​

profit = 0
for i in range(1, n):
if prices[i] > prices[i - 1]:
profit += prices[i] - prices[i - 1]

O(n) 时间、O(1) 空间。也可以理解为: 每天都可以「先卖出昨天的、再买入今天的」,所以只要今天比昨天高就赚差价。


完整代码实现​

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


class Solution:
def maxProfit(self, prices: List[int]) -> int:
"""多次交易:累加所有相邻正差价"""
profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i - 1]:
profit += prices[i] - prices[i - 1]
return profit

示例推演​

以 prices = [8,9,2,5,4,7,1] 为例,逐对比较相邻价格:

相邻对差价是否为正累计收益
8→9+1是1
9→2-7否1
2→5+3是4
5→4-1否4
4→7+3是7
7→1-6否7

最终收益 7,与答案一致。


复杂度分析​

解法时间复杂度空间复杂度说明
贪心累加正差价O(n)O(1)推荐
状态机 DP(持有/空仓)O(n)O(1)同样 O(1),思路更通用

易错点总结​

1. 把「多次交易」当成「多笔独立交易」去枚举​

不需要找买卖点,逐日累加正差价即可,避免复杂的区间划分。

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

单调下跌时没有任何正差价,累加结果自然是 0,天然满足要求。

3. 认为「必须持有一天以上」​

当天买当天卖收益为 0,不影响结果;但被问到时要知道不禁止。


扩展思考​

  • 若限定最多 k 笔交易,就用状态机 DP(见 BM82)。
  • 若加上手续费或冷冻期,转移方程需要相应调整。

相关题目​

自测​

加载评论中...