买卖股票的最佳时机

好的,我们用 dp[i][0]dp[i][1] 来分别表示第 i 天持有股票和不持有股票时的最大收益。我们来详细分析一下这种动态规划状态转移的方式。

动态规划定义

  • dp[i][0]:表示在第 i 天持有股票时的最大收益。
  • dp[i][1]:表示在第 i 天不持有股票时的最大收益。

状态转移方程

  1. 对于 dp[i][0](第 i 天持有股票)

    • 有两种情况:
      1. 昨天也持有股票:即 dp[i-1][0] 的状态继续到今天。
      2. 昨天没有股票,但今天买入了股票:那么今天的现金 = 昨天不持有股票的最大收益 dp[i-1][1] 减去今天买入股票的价格 prices[i]
    • 状态转移方程:
      [
      dp[i][0] = \max(dp[i-1][0], dp[i-1][1] - prices[i])
      ]
  2. 对于 dp[i][1](第 i 天不持有股票)

    • 也有两种情况:
      1. 昨天就没有股票:即 dp[i-1][1] 的状态继续到今天。
      2. 昨天持有股票,但今天卖出了:那么今天的现金 = 昨天持有股票的最大收益 dp[i-1][0] 加上今天卖出股票的价格 prices[i]
    • 状态转移方程:
      [
      dp[i][1] = \max(dp[i-1][1], dp[i-1][0] + prices[i])
      ]

初始条件

  1. 第0天持有股票时的最大收益 dp[0][0]

    • 由于还没有买入操作,设为 -prices[0],表示买入股票花费的钱。
      [
      dp[0][0] = -prices[0]
      ]
  2. 第0天不持有股票时的最大收益 dp[0][1]

    • 还没有买卖操作,收益为 0
      [
      dp[0][1] = 0
      ]

最终结果

整个数组遍历结束后,我们要找到最后一天不持有股票的最大收益 dp[n-1][1],因为这是利润最大化的状态。

代码实现

def maxProfit(prices):
    if not prices:
        return 0

    n = len(prices)
    dp = [[0] * 2 for _ in range(n)]

    # 初始化
    dp[0][0] = -prices[0]  # 第0天持有股票的收益
    dp[0][1] = 0           # 第0天不持有股票的收益

    # 动态规划过程
    for i in range(1, n):
        # 第 i 天持有股票的情况
        dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i])
        # 第 i 天不持有股票的情况
        dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])

    # 最终答案为最后一天不持有股票的最大收益
    return dp[-1][1]

例子讲解

prices = [7, 1, 5, 3, 6, 4] 为例,来展示 dp 数组的变化:

天数prices[i]dp[i][0] (持有股票)dp[i][1](不持有股票)
07-7(买入股票)0
11-1(以更低价买入)0
25-1(前一天持有股票)4(今天卖出,利润 5-1=4)
33-1(前一天持有股票)4(保持不持有状态)
46-1(前一天持有股票)5(今天卖出,利润 6-1=5)
54-1(前一天持有股票)5(保持不持有状态)
  • 在最后一天 dp[5][1] = 5,即最大利润为 5。

总结

通过定义 dp[i][0]dp[i][1],我们分别表示持有和不持有股票的最大收益,并且利用状态转移方程不断更新。这种动态规划的思路帮助我们在每一天都能做出最优决策,最终求得整个过程中的最大收益。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值