股票买卖的最佳时机 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。
解题思路:贪心算法
核心思想
题目允许无限次交易,因此我们可以通过 捕捉所有上涨的波段 来最大化利润。具体来说,只要当天的价格高于前一天的价格,就将差值作为利润累加。
算法步骤
-
遍历价格数组 :从第二天开始比较每一天与前一天的价格差。
-
累加正利润 :如果当天价格高于前一天,将差价加入总利润。
-
返回结果 :遍历结束后,总利润即为所求。
代码实现
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。
总结
本题通过贪心算法将复杂问题简化为局部最优的累加,巧妙地将多次交易转化为相邻日期的利润累计。该策略高效且易于实现,是处理此类允许无限次交易问题的经典方法。