买卖股票的最佳时机 II

数组 贪心

题目描述

给定一个数组 prices,其中 prices[i] 表示第 i 天的股票价格。你可以进行 多次 买卖操作(每天最多只能持有一股股票),请计算你所能获取的最大利润。

思路分析

与"买卖股票的最佳时机 I"只允许一笔交易不同,本题允许进行任意次数的买卖。乍看之下需要找出所有"低买高卖"的区间,但实际上有一个非常简洁的贪心策略。

关键观察:如果我们把价格走势画成折线图,最大利润其实就是所有 上涨区间 的涨幅之和。而任何一段连续上涨(如 [1, 3, 5])都可以分解为相邻两天的差价之和:(3 - 1) + (5 - 3) = 4,这与 5 - 1 = 4 的结果完全一致。

因此算法非常简单:从第二天开始遍历,只要今天的价格比昨天高,就把差价累加到总利润中。这等价于在每一个上涨的前一天买入、后一天卖出,贪心地捕获了所有可获取的利润。

示例代码

/**
 * @param prices - 每日股票价格数组
 * @returns 最大总利润
 *
 * @example
 * maxProfitV2([7, 1, 5, 3, 6, 4]) // 7  (第2天买入第3天卖出 +4,第4天买入第5天卖出 +3)
 * maxProfitV2([1, 2, 3, 4, 5])    // 4  (第1天买入第5天卖出)
 * maxProfitV2([7, 6, 4, 3, 1])    // 0  (价格持续下跌,无法获利)
 */
export function maxProfitV2(prices: number[]): number {
  // 累计总利润
  let totalProfit = 0;

  // 从第二天开始,逐日比较
  for (let i = 1; i < prices.length; i++) {
    if (prices[i] > prices[i - 1]) {
      // 今天比昨天贵,累加这段上涨的差价(相当于昨天买今天卖)
      totalProfit += prices[i] - prices[i - 1];
    }
  }

  return totalProfit;
}

复杂度分析

  • 时间复杂度O(n),其中 n 为数组长度。只需一次遍历,每个元素仅被访问一次。
  • 空间复杂度O(1)。只使用了 totalProfit 一个辅助变量,与输入规模无关。

示例演示

prices = [7, 1, 5, 3, 6, 4] 为例,核心步骤如下:

天数 (i)价格前一天价格差价操作累计利润
117-6不买0
251+4累加4
335-2不买4
463+3累加7
546-2不买7
  1. 第 1 天价格 1 < 前一天 7,下跌,不操作。
  2. 第 2 天价格 5 > 前一天 1,上涨 4,累加利润 → totalProfit = 4
  3. 第 3 天价格 3 < 前一天 5,下跌,不操作。
  4. 第 4 天价格 6 > 前一天 3,上涨 3,累加利润 → totalProfit = 7
  5. 第 5 天价格 4 < 前一天 6,下跌,不操作。

最终结果为 7,等价于第 1 天买入第 2 天卖出(利润 4)+ 第 3 天买入第 4 天卖出(利润 3)。