力扣 121 买卖股票最佳时机贪心策略详解

目录

题目描述

解题思路

核心思想:贪心策略

代码实现

算法解析

步骤拆解

示例演示

正确性证明

复杂度分析

边界情况处理

其他解法对比

暴力法(不可取)

动态规划

总结


题目描述

给定一个数组 prices,其中 prices[i] 表示某股票第 i 天的价格。你只能选择 某一天 买入,并在 未来的某一不同日子 卖出。请计算这笔交易的最大利润。若不能获取利润,返回 0

示例:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(价格 = 1)买入,第 5 天(价格 = 6)卖出,利润 = 6-1 = 5。

解题思路

核心思想:贪心策略

我们需要找到最低价买入,并在之后的最高价卖出。但如何高效实现这一点?

  • 关键观察:假设在第 i 天卖出,则买入价一定是前 i 天中的最低价。

  • 贪心策略:遍历数组时,维护一个历史最低价 minPrice,并计算每天卖出时的利润,更新最大利润。


代码实现

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
  let maxProfit = 0; // 最大利润
  let minPrice = prices[0]; // 最小价格
  for (let i = 1; i < prices.length; i++) {
    // 如果当前价格小于最小价格,则更新最小价格
    if (prices[i] < minPrice) {
      minPrice = prices[i];
    }
    // 如果当前价格大于最小价格,则计算利润 (当前价格 - 最小价格)
    maxProfit = Math.max(maxProfit, prices[i] - minPrice);
  }
  return maxProfit;
};

console.log(maxProfit([7, 1, 5, 3, 6, 4]));

算法解析

步骤拆解

  1. 初始化

    • maxProfit = 0:初始最大利润为0(确保无盈利时返回0)。

    • minPrice = prices[0]:初始最低价为第1天的价格。

  2. 遍历数组

    • 从第2天开始,依次比较每一天的价格。

    • 更新最低价:如果当前价格比 minPrice 低,则更新 minPrice

    • 计算利润:如果当前价格高于 minPrice,则计算当前卖出利润,并与 maxProfit 比较,取较大值。

示例演示

以输入 [7,1,5,3,6,4] 为例:

天数价格minPrice当前利润maxProfit
17700
21100
35144
43124
56155
64135

最终最大利润为 5


正确性证明

  1. 最优子结构

    • 最大利润必然产生于某个最低价之后的高价。

    • 维护 minPrice 确保能捕捉到所有可能的买入点。

  2. 遍历覆盖所有可能性

    • 每一天都尝试以当日价格卖出,并基于历史最低价计算利润,因此不会遗漏最优解。


复杂度分析

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

  • 空间复杂度:O(1),仅用常数变量存储状态。


边界情况处理

  1. 价格递减数组:如 [7,6,5,4,3],最大利润为0。

  2. 单一价格数组:如 [5,5,5],利润为0。

  3. 数组长度为1:无法交易,直接返回0。


其他解法对比

暴力法(不可取)

  • 思路:双重循环遍历所有买入卖出组合,计算最大利润。

  • 缺点:时间复杂度 O(n²),在数据量大时超时。

动态规划

  • 思路:定义状态 dp[i] 表示前 i 天的最大利润。

  • 状态转移dp[i] = max(dp[i-1], prices[i] - minPrice)

  • 分析:本质上与贪心策略一致,但贪心法无需额外空间。


总结

贪心策略通过维护历史最低价,将问题转化为一次遍历,高效解决了一次交易的最大利润问题。
关键点

  1. 理解最低价对后续利润的决定性作用。

  2. 遍历过程中不断更新最低价和最大利润。

此方法简洁高效,是同类问题中的经典解法。对于多次交易的问题(如LeetCode 122题),需采用不同的策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端 贾公子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值