121. 买卖股票的最佳时机
题目链接121. 买卖股票的最佳时机 - 力扣(LeetCode)
思路
动规五步曲
1. dp 数组含义
-
dp[i][0]:第i天持有股票的最大现金 -
dp[i][1]:第i天不持有股票的最大现金
2. 递推公式
-
持有股票:要么之前就持有,要么今天第一次买入dp[i][0]=max(dp[i−1][0],−prices[i])
-
不持有股票:要么之前就不持有,要么今天卖出dp[i][1]=max(dp[i−1][1], dp[i−1][0]+prices[i])
3. 初始化
第一天:dp[0][0]=−prices[0],dp[0][1]=0
4. 遍历顺序
从前往后遍历每一天。
5. 结果
最后一天不持有股票的最大值:dp[n−1][1]
提交
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
if n == 0:
return 0
# dp[i][0]:第i天持有股票
# dp[i][1]:第i天不持有股票
dp = [[0] * 2 for _ in range(n)]
# 初始化第0天
dp[0][0] = -prices[0] # 第一天买入
dp[0][1] = 0 # 第一天不买入
for i in range(1, n):
# 持有:保持之前持有 / 当天新买入
dp[i][0] = max(dp[i-1][0], -prices[i])
# 不持有:保持不持有 / 当天卖出
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])
# 最后一定是不持有股票利润最大
return dp[-1][1]
122.买卖股票的最佳时机II
题目链接 122. 买卖股票的最佳时机 II - 力扣(LeetCode)
思路
跟上一道题区别就是可以无限次交易
动规五步曲
1. dp 数组定义
-
dp[i][0]:第 i 天持有股票的最大利润
-
dp[i][1]:第 i 天不持有股票的最大利润
2. 递推公式
-
持有股票:
前一天就持有;前一天不持有,当天买入dp[i][0]=max(dp[i−1][0], dp[i−1][1]−prices[i])
-
不持有股票:
前一天就不持有;前一天持有,当天卖出dp[i][1]=max(dp[i−1][1], dp[i−1][0]+prices[i])
3. 初始化
第 0 天:dp[0][0]=−prices[0],dp[0][1]=0
4. 遍历顺序
从前到后依次遍历每一天
5. 最终结果
最后一天不持有股票:dp[−1][1]
提交
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
if n == 0:
return 0
# dp[i][0]:第i天持有股票
# dp[i][1]:第i天不持有股票
dp = [[0] * 2 for _ in range(n)]
# 初始化第一天
dp[0][0] = -prices[0] # 第一天买入
dp[0][1] = 0 # 第一天不操作
for i in range(1, n):
# 当天持有:之前持有 / 当天新买
dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i])
# 当天不持有:之前空仓 / 当天卖出
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])
return dp[-1][1]
123.买卖股票的最佳时机III
题目链接 123. 买卖股票的最佳时机 III - 力扣(LeetCode)
思路
动规 5 步曲
1. dp 数组定义
一天有5 种状态:
-
dp[i][0]:第 i 天,无操作 -
dp[i][1]:第 i 天,第一次持有股票 -
dp[i][2]:第 i 天,第一次卖出完成 -
dp[i][3]:第 i 天,第二次持有股票 -
dp[i][4]:第 i 天,第二次卖出完成
2. 递推公式
第一次持有:之前就持有 / 当天第一次买入dp[i][1]=max(dp[i−1][1], dp[i−1][0]−prices[i])
第一次卖出:之前已卖出 / 当天卖出第一次dp[i][2]=max(dp[i−1][2], dp[i−1][1]+prices[i])
第二次持有:之前二次持有 / 第一次卖完再买dp[i][3]=max(dp[i−1][3], dp[i−1][2]−prices[i])
第二次卖出:之前二次卖出 / 当天卖出第二次dp[i][4]=max(dp[i−1][4], dp[i−1][3]+prices[i])
3. 初始化
dp[0][0] = 0
dp[0][1] = -prices[0]
dp[0][2] = -∞
dp[0][3] = -∞
dp[0][4] = -∞
4. 遍历顺序
从前往后遍历每一天
5. 结果
答案:max(dp[n−1][2], dp[n−1][4])(可以只做 1 笔、也可以做 2 笔)
股票三道题联动记忆:
-
只能 1 次:买入只能用
-prices[i] -
无限次:买入用
前一天卖出状态-价格 -
最多 2 次:增加二次交易状态拆分
提交
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
if n == 0:
return 0
# 5个状态:0无操作 1第一次持有 2第一次卖出 3第二次持有 4第二次卖出
dp = [[0] * 5 for _ in range(n)]
INF = float("inf")
# 初始化第0天
dp[0][0] = 0
dp[0][1] = -prices[0]
dp[0][2] = -INF
dp[0][3] = -INF
dp[0][4] = -INF
for i in range(1, n):
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])
dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])
dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])
# 最多两笔,取完成1笔 / 完成2笔的最大值,不能为负
return max(dp[-1][2], dp[-1][4], 0)