买卖股票的最佳时机 II递推内存优化

在这里插入图片描述

股票买卖最大利润问题:动态规划解法

本文将介绍如何通过动态规划解决经典的“股票买卖最大利润”问题,并通过代码实例进行详细分析。

问题描述

给定一个整数数组 prices,其中 prices[i] 表示某天的股票价格,你可以选择在某些天买入和卖出股票,且每次只能买入一次,卖出一次,求你能够获得的最大利润。

解释

  • 你有 n 天的股票价格,你可以选择在任意一个时间点买入和卖出股票。
  • 买入和卖出操作必须满足:买入操作发生在卖出操作之前。
  • 你可以进行多次买入卖出操作,但不能同时持有多只股票。

动态规划解法

状态定义

我们可以使用两个变量来表示不同的状态:

  • f0:表示不持有股票的最大利润。
  • f1:表示持有股票的最大利润。

状态转移方程

在每一天,最优策略是基于前一天的状态决定的。因此,我们有以下两种状态转移:

  1. 更新 f0:如果今天你没有持有股票,可能是:

    • 保持不持有状态,f0 不变;
    • 卖出股票,获得利润,更新 f0f1 + p,其中 p 是今天的股价。

    所以,更新 f0 的公式为:
    [
    f0 = \max(f0, f1 + p)
    ]

  2. 更新 f1:如果今天你持有股票,可能是:

    • 保持持有状态,f1 不变;
    • 从没有持有股票转变为持有股票,更新 f1f0 - p,即买入股票。

    所以,更新 f1 的公式为:
    [
    f1 = \max(f1, f0 - p)
    ]

初始化

  • 初始时,没有持有股票,因此 f0 = 0
  • 初始时,持有股票是不可能的,因此 f1 = -inf(负无穷,表示不可达状态)。

最终结果

最终返回 f0,即在所有交易结束后,且没有持有股票时的最大利润。

代码实现

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        f0 = 0  # 不持有股票的最大利润
        f1 = float('-inf')  # 持有股票的最大利润
        
        # 遍历每一天的股票价格
        for p in prices:
            # 如果今天没有持有股票,最大利润是保持不持有或卖出股票
            new_f0 = max(f0, f1 + p)
            # 如果今天持有股票,最大利润是保持持有或买入股票
            f1 = max(f1, f0 - p)
            # 更新不持有股票的最大利润
            f0 = new_f0
        
        # 返回最终不持有股票时的最大利润
        return f0

代码解析

  1. 初始化

    • f0 = 0,表示开始时没有持有股票,利润为零。
    • f1 = -inf,表示开始时不可能有持有股票的利润。
  2. 遍历价格数组

    • 每一天更新 f0f1 的值:
      • new_f0 = max(f0, f1 + p):如果不持有股票,今天的利润是“保持不持有”或“卖出股票”中的较大值。
      • f1 = max(f1, f0 - p):如果持有股票,今天的利润是“保持持有”或“买入股票”中的较大值。
    • 更新 f0,即不持有股票的最大利润。
  3. 返回结果

    • 最终返回 f0,即不持有股票时的最大利润。

图示解析

动态规划过程图

如上图所示,动态规划通过不断更新 f0f1,考虑每一天的买入卖出决策,从而推导出最终的最大利润。

时间和空间复杂度

  • 时间复杂度:O(n),其中 nprices 数组的长度。我们只遍历一次 prices 数组。
  • 空间复杂度:O(1),只使用了常数空间来存储 f0f1

总结

通过动态规划的思想,我们能够高效地解决这个股票买卖问题。通过维护两个状态变量 f0f1,我们可以从前一天的状态推导出最优的买卖决策,最终得到最大利润。相比暴力搜索的方法,这种方法更加高效,时间复杂度为 O(n)。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n=len(prices)
        f0=0
        f1=-inf#初始化边界 因为下一次的最优赚钱方案一定之和上一次的状态有关系,那么可以用两个int变量来存储
        for p in prices:
            new_f0=max(f0,f1+p)#如果下一次是没有持有的,那么下一次的最大值肯定是”保持没有持有“或者“持有但是卖出”里面选一
            f1=max(f1,f0-p)#这里设置new_f0的原因是,我的f1依赖于上一次的状态,如果new_f0就变成依赖想和一次的状态,显然不对
            f0=new_f0#如果下一次是持有的,那么下一次的最大值肯定是“保持持有”或者“没有持有但是买入,但是买入可以让下次赚更多,因为是互相关联的”
        return f0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值