在问 · 算法题解

122. 买卖股票的最佳时机 II

中等贪心贪心累加上涨差价力扣原题 ↗

题目描述

输入数组 prices,prices[i] 是某支股票第 i 天的价格。

每天都可以选择买入、卖出或不操作,交易次数不限。但手上同一时刻最多只能有一股。同一天可以先卖出再买入。

返回能获得的最大总利润。

示例 1
输入:prices = [7,1,5,3,6,4]
输出:7

解释:价格 1 买、5 卖赚 4,再 3 买、6 卖赚 3,共 7。

示例 2
输入:prices = [1,2,3,4,5]
输出:4

解释:第一天买入、最后一天卖出,赚 4。

示例 3
输入:prices = [7,6,4,3,1]
输出:0

解释:价格一直下跌,不交易,利润为 0。

数据范围

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

解题思路:贪心累加上涨差价

交易次数不限,可以把任何一段上涨拆成相邻两天的上涨之和:prices[j] - prices[i] = Σ(prices[k] - prices[k-1])。所以只要把所有正的单日涨幅加起来即可,下跌的那天不持有。

为什么正确

处理到第 i 天时,profit 是前 i 天所有正涨幅之和,也就是前 i 天的最大利润。

复杂度分析

时间 O(n),空间 O(1)。

易错点

累加涨幅不等于真实的买卖操作,只是利润相同:连续上涨 1→2→3 赚 2,等价于 1 买 3 卖。不要和 121 题(只能交易一次)混淆。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

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

载入编辑器,自己跑一遍 →

其他解法

两种解法都是 O(n) 时间、O(1) 空间;贪心最简洁,状态机动态规划是股票系列题目的通用模板。

解法 2:持有状态动态规划 时间 O(n),空间 O(1)

cash 表示当天结束时不持股的最大利润,hold 表示持股的最大利润。初始 cash = 0,hold = -prices[0]。每天用前一天的值更新:cash = max(cash, hold + p),hold = max(hold, cash - p)。最后返回 cash。

比贪心多想一步,但状态定义可以直接推广到含手续费、冷冻期、限制交易次数的变体。贪心只适用于不限次数且无额外成本的情形。

from typing import List

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        cash, hold = 0, -prices[0]
        for p in prices[1:]:
            cash, hold = max(cash, hold + p), max(hold, cash - p)
        return cash

贪心 专题的其他题目

查看 贪心 全部题目 →