返回

回旋复复——动态规划下的123号难题

后端

在股票交易中,把握时机是关键。

股市瞬息万变,投资者需要具备敏锐的洞察力,捕捉每一个潜在的盈利机会。动态规划是一种强大的算法技术,它能够帮助我们对未来的可能情况进行分析,并找到最优的决策方案。

在本文中,我们将以一道经典的股票交易难题——123. 买卖股票的最佳时机 III作为例子,展示动态规划的强大功能。

题目

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

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

解题思路

这道题目的核心在于如何确定买卖股票的最佳时机。

我们可以将这个问题分解为以下几个子问题:

  1. 在第 i 天之前,不进行任何交易,所能获得的最大利润是多少?
  2. 在第 i 天之前,进行一次买入操作,所能获得的最大利润是多少?
  3. 在第 i 天之前,进行一次买入操作并一次卖出操作,所能获得的最大利润是多少?

通过解决这些子问题,我们可以逐步推导出最终的解法。

动态规划状态转移方程

根据上述子问题,我们可以定义以下动态规划状态转移方程:

dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
dp[i][k][2] = max(dp[i-1][k][2], dp[i-1][k][1] + prices[i])

其中:

  • dp[i][k][0] 表示在第 i 天之前,不进行任何交易,所能获得的最大利润。
  • dp[i][k][1] 表示在第 i 天之前,进行一次买入操作,所能获得的最大利润。
  • dp[i][k][2] 表示在第 i 天之前,进行一次买入操作并一次卖出操作,所能获得的最大利润。
  • k 表示最多可以进行的交易次数。
  • prices[i] 表示第 i 天的股票价格。

代码实现

def maxProfit(prices):
    k = 2  # 最多可以进行的交易次数
    n = len(prices)
    dp = [[[0 for _ in range(3)] for _ in range(k + 1)] for _ in range(n + 1)]

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

    return dp[n][k][2]

算法复杂度

该算法的时间复杂度为 O(n * k),其中 n 为股票价格数组的长度,k 为最多可以进行的交易次数。

总结

动态规划是一种强大的算法技术,它能够帮助我们解决许多复杂的优化问题。在股票交易中,动态规划可以帮助我们找到买卖股票的最佳时机,实现利润最大化。

在本文中,我们以一道经典的股票交易难题——123. 买卖股票的最佳时机 III作为例子,展示了动态规划的强大功能。我们通过定义动态规划状态转移方程,并使用代码实现,求得了该难题的最优解。