LeetCode 121. 买卖股票的最佳时机 动态规划详解

121. 买卖股票的最佳时机

题目来源

121. 买卖股票的最佳时机

题目分析

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

题目难度

  • 难度:简单

题目标签

  • 标签:动态规划

题目限制

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

解题思路

思路:动态规划

  1. 问题定义

    • 本题要求通过选择适当的买入和卖出时机,计算在单次买卖操作中所能获得的最大利润。
  2. 核心算法

    • 动态规划:我们使用一个变量来记录当前遇到的最低价格,另一个变量来记录当前所能获得的最大利润。随着遍历股票价格数组,不断更新最低价格和最大利润。
  3. 关键步骤

    • 遍历数组时,更新最低价格 minPrice 和最大利润 maxProfit
    • 通过与当前价格计算差值来判断是否需要更新最大利润。

核心算法步骤

  1. 初始化变量

    • minPrice 记录股票的最低价格,初始为 prices[0]
    • maxProfit 记录最大利润,初始为 0
  2. 遍历价格数组

    • 对每个价格 price,更新 minPrice 为当前的最小价格。
    • 计算 price - minPrice 并更新 maxProfit 为当前最大利润。
  3. 返回结果

    • 遍历结束后,maxProfit 即为最大利润。

代码实现

以下是动态规划法的 Java 代码实现:

/**
 * 121. 买卖股票的最佳时机
 * @param prices 股票价格数组
 * @return 最大利润
 * @apiNote 动态规划,时间复杂度O(n),空间复杂度O(1)
 */
public int maxProfit3(int[] prices) {
    int minPrice = prices[0];
    int maxProfit = 0;
    for (int price : prices) {
        minPrice = Math.min(minPrice, price);
        maxProfit = Math.max(maxProfit, price - minPrice);
    }
    return maxProfit;
}

代码解读

  • 初始化最低价格minPrice 被初始化为数组的第一个元素。
  • 遍历更新:在遍历数组时,minPrice 不断更新为当前遍历到的最低价格,maxProfit 则更新为当前价格与最低价格的差值中的最大值。
  • 返回最大利润:循环结束后,maxProfit 存储的即为最大利润。

性能分析

  • 时间复杂度O(n),遍历一次数组即可获得最大利润。
  • 空间复杂度O(1),只使用了常数级别的辅助空间。

复杂度效果

复杂度

测试用例

你可以使用以下测试用例来验证代码的正确性:

// 测试用例1
int[] prices1 = {7, 1, 5, 3, 6, 4};
int result1 = maxProfit3(prices1); 
System.out.println(result1); // 输出: 5

// 测试用例2
int[] prices2 = {7, 6, 4, 3, 1};
int result2 = maxProfit3(prices2); 
System.out.println(result2); // 输出: 0

扩展讨论

优化写法

  • 单次遍历法:通过单次遍历数组即可在 O(n) 时间复杂度下找到最大利润,这是时间最优解法。

其他实现

  • 暴力法:通过两重循环枚举所有的买卖组合,时间复杂度为 O(n^2),不推荐。

总结

这道题目主要考察了对动态规划的理解,通过对最低价格的动态更新和利润的实时计算,可以在 O(n) 的时间复杂度内得到最优解。


  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值