algorithm-base:买卖股票的最佳时机动画教程,动态规划解法
你还在为动态规划问题感到头疼吗?面对股票买卖类题目时是否总是无从下手?本文将通过动画模拟的方式,用通俗易懂的语言带你彻底搞懂「买卖股票的最佳时机」问题的动态规划解法,读完你将能够:
- 理解股票买卖问题的动态规划状态定义
- 掌握状态转移方程的推导方法
- 学会优化动态规划的空间复杂度
- 解决各种变种的股票买卖问题
问题引入
假设你有一个数组,其中第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。
注意:你不能在买入股票前卖出股票。
示例:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(价格 = 1)的时候买入,在第 5 天(价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
动态规划解题思路
状态定义
我们定义两个状态来描述问题:
dp[i][0]:表示第 i 天不持有股票时的最大利润dp[i][1]:表示第 i 天持有股票时的最大利润
状态转移方程
对于 dp[i][0](不持有股票),有两种情况:
- 第 i-1 天也不持有股票,今天什么都不做
- 第 i-1 天持有股票,今天卖出
所以状态转移方程为:dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
对于 dp[i][1](持有股票),有两种情况:
- 第 i-1 天也持有股票,今天什么都不做
- 第 i 天买入股票
所以状态转移方程为:dp[i][1] = max(dp[i-1][1], -prices[i])
初始状态
dp[0][0] = 0:第 0 天不持有股票,利润为 0dp[0][1] = -prices[0]:第 0 天持有股票,利润为负的买入价格
空间优化
由于每次计算只需要前一天的状态,我们可以使用两个变量来代替二维数组,将空间复杂度从 O(n) 优化到 O(1):
cash = 0 # 不持有股票的最大利润
hold = -prices[0] # 持有股票的最大利润
for i in range(1, len(prices)):
cash = max(cash, hold + prices[i])
hold = max(hold, -prices[i])
return cash
动画模拟过程
下面通过动画来模拟整个计算过程(假设输入 prices = [7,1,5,3,6,4]):
第 0 天
- 不持有股票:cash = 0
- 持有股票:hold = -7
第 1 天(价格=1)
- 不持有股票:max(0, -7+1=-6) → 0
- 持有股票:max(-7, -1) → -1
第 2 天(价格=5)
- 不持有股票:max(0, -1+5=4) → 4
- 持有股票:max(-1, -5) → -1
第 3 天(价格=3)
- 不持有股票:max(4, -1+3=2) → 4
- 持有股票:max(-1, -3) → -1
第 4 天(价格=6)
- 不持有股票:max(4, -1+6=5) → 5
- 持有股票:max(-1, -6) → -1
第 5 天(价格=4)
- 不持有股票:max(5, -1+4=3) → 5
- 持有股票:max(-1, -4) → -1
最终结果为 5,与示例一致。
变种问题拓展
允许无限次交易
如果允许进行无限次交易,状态转移方程只需做一点修改: dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
完整代码:
cash = 0
hold = -prices[0]
for i in range(1, len(prices)):
new_cash = max(cash, hold + prices[i])
new_hold = max(hold, cash - prices[i])
cash, hold = new_cash, new_hold
return cash
最多允许两次交易
对于最多允许两次交易的情况,我们需要定义四个状态:
dp[i][0]:未进行任何交易dp[i][1]:进行了一次买入dp[i][2]:进行了一次买入和一次卖出dp[i][3]:进行了两次买入和一次卖出dp[i][4]:进行了两次买入和两次卖出
具体实现可以参考项目中的动态规划章节 【动画模拟】动态规划详解
总结
动态规划是解决股票买卖问题的有效方法,其核心在于:
- 定义清晰的状态
- 推导出正确的状态转移方程
- 合理初始化状态
- 必要时进行空间优化
通过本文的学习,你已经掌握了股票买卖问题的动态规划解法。如果想进一步巩固,可以尝试解决以下问题:
希望本文能帮助你更好地理解动态规划思想,在算法学习的道路上更进一步!如果你觉得本文对你有帮助,欢迎点赞、收藏、关注三连,也欢迎在评论区交流讨论。
关于项目
本文内容基于 algorithm-base 项目,这是一个致力于用动画将算法说的通俗易懂的开源项目。项目作者是一位酷爱做饭的程序员,他的面试网站是 www.chengxuchu.com。
项目中还有更多像这样的动画算法教程,涵盖了二分查找、二叉树、动态规划等多个领域,如:
如果你对算法学习感兴趣,不妨去项目中探索更多精彩内容!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



