股票买卖的最佳时机 II:贪心策略详解

165 阅读4分钟

股票买卖的最佳时机 II:贪心策略详解

目录

[TOC]

问题描述

给定一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。设计一个算法计算你所能获取的最大利润。你可以多次买卖该股票,但必须遵循以下规则:

  • 在再次购买前必须出售掉之前的股票。

示例
输入: prices = [7,1,5,3,6,4]
输出: 7
解释:在第 2 天买入(价格 = 1),第 3 天卖出(价格 = 5),利润为 4;在第 4 天买入(价格 = 3),第 5 天卖出(价格 = 6),利润为 3。总利润为 4 + 3 = 7。


解题思路:贪心算法

核心思想

题目允许无限次交易,因此我们可以通过 捕捉所有上涨的波段 来最大化利润。具体来说,只要当天的价格高于前一天的价格,就将差值作为利润累加。

算法步骤
  1. 遍历价格数组 :从第二天开始比较每一天与前一天的价格差。

  2. 累加正利润 :如果当天价格高于前一天,将差价加入总利润。

  3. 返回结果 :遍历结束后,总利润即为所求。

代码实现
var maxProfit = function (prices) {
  let maxProfit = 0;
  for (let i = 1; i < prices.length; i++) {
    const profit = prices[i] - prices[i - 1];
    if (profit > 0) {
      maxProfit += profit;
    }
  }
  return maxProfit;
};

算法正确性分析

为什么贪心策略有效?

假设股票连续多日上涨,例如价格为 [1, 3, 5]

  • 单次交易 :第 1 天买入,第 3 天卖出,利润为 5 - 1 = 4

  • 多次交易 :第 1 天买入第 2 天卖出(利润 2),第 2 天买入第 3 天卖出(利润 2),总利润仍为 4

无论是否拆分交易,总利润相同。因此,贪心策略通过累加所有正差值,能够覆盖所有可能的上涨波段,确保结果最优。

所有可能情况的详细分析
1. 连续上涨:捕捉所有上涨波段

示例prices = [1, 2, 3, 4]

  • 相邻差值为 +1, +1, +1 ,总利润为 1+1+1=3

  • 实际策略 :第 1 天买入,第 4 天卖出,利润为 4-1=3
    结论 :无论是否拆分交易,总利润相同。贪心策略通过累加所有正利润,自然覆盖了连续上涨的最优解。


2. 连续下跌:不参与任何交易

示例prices = [4, 3, 2, 1]

  • 相邻差值为 -1, -1, -1 ,总利润为 0

  • 实际策略 :不进行任何买卖,避免亏损。
    结论 :贪心算法自动忽略所有负利润,确保在下跌时不操作。


3. 波动市(涨跌交替):仅累加上涨波段

示例prices = [1, 3, 2, 4]

  • 相邻差值为 +2, -1, +2 ,总利润为 2+2=4

  • 实际策略 :第 1 天买入,第 2 天卖出(利润 2);第 3 天买入,第 4 天卖出(利润 2)。
    结论 :贪心策略通过捕捉所有局部上涨,忽略下跌,保证总利润最大化。


4. 先涨后跌:在价格峰值前卖出

示例prices = [1, 2, 3, 2, 1]

  • 相邻差值为 +1, +1, -1, -1 ,总利润为 1+1=2

  • 实际策略 :第 1 天买入,第 3 天卖出(利润 2);后续下跌不操作。
    结论 :算法在价格下跌前已通过累加正利润锁定收益。


5. 先跌后涨:在低点重新买入

示例prices = [3, 1, 2, 4]

  • 相邻差值为 -2, +1, +2 ,总利润为 1+2=3

  • 实际策略 :第 2 天买入,第 4 天卖出(利润 3)。
    结论 :下跌时不操作,但在后续上涨时重新参与,确保不错过机会。


复杂度分析

  • 时间复杂度 :O(n),仅需遍历数组一次。

  • 空间复杂度 :O(1),仅使用常数空间。


边界条件处理

  • 空数组或单日价格 :当 prices.length <= 1 时,循环不会执行,直接返回 0

  • 价格持续下跌 :所有差值为负,总利润为 0


总结

本题通过贪心算法将复杂问题简化为局部最优的累加,巧妙地将多次交易转化为相邻日期的利润累计。该策略高效且易于实现,是处理此类允许无限次交易问题的经典方法。