返回

打卡算法 | LeetCode 123. 买卖股票的最佳时机 III

后端

  • 【高阶算法解析】突破视野,投资中的关键策略

前言

近年来,算法和人工智能蓬勃发展,LeetCode作为算法学习平台,吸引了大量算法爱好者。同时,股票交易也越来越受到人们的关注。这篇文章将结合这两个领域,介绍LeetCode上的经典股票交易问题 - 123. 买卖股票的最佳时机 III,并提供详细的算法解析。

问题介绍

LeetCode 123. 买卖股票的最佳时机 III

给定一个数组,代表某只股票每日的价格。你可以完成至多两次交易。计算你所能获得的最大利润。

示例 1:

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)买入,在第 6 天(股票价格 = 3)卖出,可获得利润 = 3-0 = 3 。
      然后,在第 7 天(股票价格 = 1)买入,在第 8 天(股票价格 = 4)卖出,可获得利润 = 4-1 = 3 。
总利润为 6 = 3 + 3 

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)买入,在第 5 天 (股票价格 = 5)卖出,可获得利润 = 5-1 = 4 。
总利润为 4 

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这个例子中, 没有一次交易能产生正利润,所以最大利润为 0

算法分析

这个问题可以用动态规划算法解决。

首先,我们需要定义一个状态:dp[i][k][s],其中:

  • i 是当前天数
  • k 是剩余交易次数
  • s 是当前状态(0 表示持有股票,1 表示不持有股票)

然后,我们需要计算每个状态的最大利润。

状态转移方程:

  • 如果 s = 0,则 dp[i][k][s] = max(dp[i-1][k][s], dp[i-1][k-1][1] + prices[i])
  • 如果 s = 1,则 dp[i][k][s] = max(dp[i-1][k][s], dp[i-1][k][0] - prices[i])

初始状态:

  • dp[0][0][0] = 0
  • dp[0][0][1] = -prices[0]
  • dp[0][1][0] = 0
  • dp[0][1][1] = -prices[0]

终止状态:

  • dp[i][k][s],其中 i = nk = 2s = 0s = 1

代码实现

def maxProfit(prices):
  n = len(prices)
  dp = [[[0 for _ in range(2)] for _ in range(3)] for _ in range(n)]

  dp[0][0][0] = 0
  dp[0][0][1] = -prices[0]
  dp[0][1][0] = 0
  dp[0][1][1] = -prices[0]

  for i in range(1, n):
    for k in range(2):
      for s in range(2):
        if s == 0:
          dp[i][k][s] = max(dp[i-1][k][s], dp[i-1][k-1][1] + prices[i])
        else:
          dp[i][k][s] = max(dp[i-1][k][s], dp[i-1][k][0] - prices[i])

  return dp[n-1][2][0]


# 测试代码
prices = [3,3,5,0,0,3,1,4]
print(maxProfit(prices))  # 输出:6

prices = [1,2,3,4,5]
print(maxProfit(prices))  # 输出:4

prices = [7,6,4,3,1]
print(maxProfit(prices))  # 输出:0

总结

在这篇文章中,我们介绍了LeetCode上的经典股票交易问题 - 123. 买卖股票的最佳时机 III,并提供了详细的算法解析。我们还介绍了如何使用动态规划算法解决这个问题。希望这篇文章对你有所帮助。