搞定股票交易难题,三步制胜【123.买卖股票的最佳时机 III】
2023-08-17 10:38:36
剖析股票交易的黄金法则:掌握 123. 买卖股票的最佳时机 III
在瞬息万变的股票市场中,把握买卖时机至关重要。想要在股海中乘风破浪,精通动态规划算法不可或缺,而【123. 买卖股票的最佳时机 III】就是其中一道经典题目。
理解问题要点
这道题要求我们设计一种算法,计算给定股票价格数组中进行最多两次交易(买卖)所能获得的最大利润。
- 关键点: 最多两次交易,即最多买卖两次。
- 目标: 获得最大利润。
剖析动态规划思想
动态规划是一种强大的算法技术,能将大问题分解成若干小问题,逐步求解并合并,最终得到全局最优解。
状态函数定义
在【123. 买卖股票的最佳时机 III】中,我们定义状态函数 dp[i][k][0/1] 来表示在前 i 天内,进行了 k 次交易,目前是否持有股票的状态。
- dp[i][k][0]:在前 i 天内,进行了 k 次交易,目前不持有股票。
- dp[i][k][1]:在前 i 天内,进行了 k 次交易,目前持有股票。
状态转移方程推导
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][0] 和 dp[i][k][1] 的计算都依赖于三个子问题的结果。因此,我们可以使用三维数组来存储子问题的结果,然后逐步计算出每个子问题的最优值。
def maxProfit(prices):
n = len(prices)
dp = [[[0] * 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):
dp[i][0][0] = max(dp[i-1][0][0], dp[i-1][0][1] + prices[i])
dp[i][0][1] = max(dp[i-1][0][1], dp[i-1][1][0] - prices[i])
dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][1][1] + prices[i])
dp[i][1][1] = max(dp[i-1][1][1], dp[i-1][0][0] - prices[i])
return dp[n-1][1][0]
实战应用
掌握了这道题目的解决方法,我们在股票市场中就能大显身手。
- 把握买入时机: 当 dp[i][k][0] 中,dp[i-1][k][1] + prices[i] 表示前一天持有股票,今天卖出的利润大于 dp[i-1][k][0] 时,表明今天是合适的买入时机。
- 把握卖出时机: 当 dp[i][k][1] 中,dp[i-1][k-1][0] - prices[i] 表示前一天不持有股票,今天买入的利润大于 dp[i-1][k][1] 时,表明今天是合适的卖出时机。
结语
【123. 买卖股票的最佳时机 III】是一道经典的动态规划问题,通过对问题的剖析和状态函数的定义,我们可以逐步求解出全局最优解。掌握了这道题目的解决方法,你将在股票交易的道路上更进一步,洞悉市场玄机,实现收益最大化。
常见问题解答
-
为什么需要定义两个状态 dp[i][k][0] 和 dp[i][k][1] 来表示持有和不持有股票的状态?
因为我们需要跟踪在不同状态下的最大利润,以找出最佳交易策略。
-
状态转移方程中为什么 dp[i][k][1] 的计算依赖于 dp[i-1][k-1][0]?
因为进行一次交易需要先不持有股票,然后才能买入股票。
-
为什么在初始化时将 dp[0][0][1] 和 dp[0][1][1] 设置为负数?
因为在第一天之前,不可能持有股票或卖出股票,因此将利润初始化为负数。
-
如何确定最多进行两次交易的最佳交易时间点?
通过计算 dp[n-1][1][0],其中 n 是股票价格数组的长度,可以得到最大利润,然后通过回溯状态转移方程,确定最佳交易时间点。
-
这道题目的动态规划方法是否适用于其他股票交易问题?
是的,动态规划方法可以用于解决其他需要考虑状态和决策的股票交易问题。