class Solution:
def maxProfit(self, prices: List[int]) -> int:
# 动态规划
# 状态:天数,买,卖
# 5种选择:无操作,1次买操作,1次买的基础上1次卖,第2次买(第一次交易完成的前提下开始),第二次买的基础上卖(完成两笔交易)
# dp数组存储当天的最终状态
n = len(prices)
if n==0: return 0
# dp = [[[0]*3]*3]*n
dp=[ [[0,0,0],[0,0,0] ] for i in range(0,n) ]
# base case
# 第1天无交易【不买不卖】
dp[0][0][0] = 0
# 第一天没买还卖?所以卖1支两支都有问题
dp[0][0][1] = float('-inf')
dp[0][0][2] = float('-inf')
# 第1天买入1支【买了东西此时钱少了】
dp[0][1][0] = -prices[0]
# 第一天买了再卖/买了1支卖两支?也不可以
dp[0][1][1] = float('-inf')
dp[0][1][2] = float('-inf')
# 对于之后的每一天进行操作
for i in range(1,n):
# 当天末: 未持股的状态,没有买卖记录
dp[i][0][0] = 0
# 当天末: 未持股的状态,但是有卖出一支的记录,之前卖的吧(记录上次的状态)/今天卖的算钱(之前手里有一支并且没有卖出记录的情况下加上今天的钱)!
dp[i][0][1] = max(dp[i-1][0][1],dp[i-1][1][0]+prices[i])
# 当天末: 未持股的状态,但是有两支卖出记录,之前卖的(上次的状态)/今天卖的算钱(上次手里有1支,也有1次卖出的记录了,加上今天的钱)
dp[i][0][2] = max(dp[i-1][0][2],dp[i-1][1][1]+prices[i])
# 当天末: 持1股,无卖出记录,昨天买的(上次的状态),今天买的(从没有交易过,所以直接0-今天这股价钱,当然也可以用上次的没买的状态减钱)
dp[i][1][0] = max(dp[i-1][1][0],dp[i-1][0][0]-prices[i])
# 当天末: 持1股,卖出1支,第二次交易状态,昨天买的(上次状态),今天买的(上次持0股交易1次的状态【第一次结束】下减钱)
dp[i][1][1] = max(dp[i-1][1][1],dp[i-1][0][1]-prices[i])
# 当天末: 持1股,卖出2支,不可能
dp[i][1][2] = float('-inf')
# 两次赚钱的可能,最后一天 “持0股,卖出1支” 以及 “持0股,卖出2支”
return max(dp[n-1][0][1],dp[n-1][0][2],0)
第二种简单的:
class Solution:
def maxProfit(self, prices: List[int]) -> int:
# 动态规划
# 状态:天数,买,卖
# 5种选择:无操作,1次买操作,1次买的基础上1次卖,第2次买(第一次交易完成的前提下开始),第二次买的基础上卖(完成两笔交易)
# dp数组存储当天的最终状态
"""
n = len(prices)
if n==0: return 0
# dp = [[[0]*3]*3]*n
dp=[ [[0,0,0],[0,0,0] ] for i in range(0,n) ]
# base case
# 第1天无交易【不买不卖】
dp[0][0][0] = 0
# 第一天没买还卖?所以卖1支两支都有问题
dp[0][0][1] = float('-inf')
dp[0][0][2] = float('-inf')
# 第1天买入1支【买了东西此时钱少了】
dp[0][1][0] = -prices[0]
# 第一天买了再卖/买了1支卖两支?也不可以
dp[0][1][1] = float('-inf')
dp[0][1][2] = float('-inf')
# 对于之后的每一天进行操作
for i in range(1,n):
# 当天末: 未持股的状态,没有买卖记录
dp[i][0][0] = 0
# 当天末: 未持股的状态,但是有卖出一支的记录,之前卖的吧(记录上次的状态)/今天卖的算钱(之前手里有一支并且没有卖出记录的情况下加上今天的钱)!
dp[i][0][1] = max(dp[i-1][0][1],dp[i-1][1][0]+prices[i])
# 当天末: 未持股的状态,但是有两支卖出记录,之前卖的(上次的状态)/今天卖的算钱(上次手里有1支,也有1次卖出的记录了,加上今天的钱)
dp[i][0][2] = max(dp[i-1][0][2],dp[i-1][1][1]+prices[i])
# 当天末: 持1股,无卖出记录,昨天买的(上次的状态),今天买的(从没有交易过,所以直接0-今天这股价钱,当然也可以用上次的没买的状态减钱)
dp[i][1][0] = max(dp[i-1][1][0],dp[i-1][0][0]-prices[i])
# 当天末: 持1股,卖出1支,第二次交易状态,昨天买的(上次状态),今天买的(上次持0股交易1次的状态【第一次结束】下减钱)
dp[i][1][1] = max(dp[i-1][1][1],dp[i-1][0][1]-prices[i])
# 当天末: 持1股,卖出2支,不可能
dp[i][1][2] = float('-inf')
# 两次赚钱的可能,最后一天 “持0股,卖出1支” 以及 “持0股,卖出2支”
return max(dp[n-1][0][1],dp[n-1][0][2],0)
"""
n = len(prices)
if n <= 1: return 0
# 第一天状态:
# 01/02: 持股0卖出1/2不可能
# 10: 第一天买了, 持股1卖出0 此时直接减去买股票的钱
# 11: 第一天买第一天卖,不管,其实利润是0
n_01, n_02, n_10, n_11 = float("-inf"), float("-inf"), -prices[0], float("-inf")
for i in range(1, n):
# c_01: n_10+prices[i] 从持股1卖出0 到 持股0卖出1【第一次交易结束】
c_01 = max(n_01, n_10+prices[i])
# c_02: n_11+prices[i] 从持股1卖出1 到 持股0卖出2 【第二次交易结束】
c_02 = max(n_02, n_11+prices[i])
# c_10: 0 - prices[i] 第一次持股, 总价直接扣 【第一次买】
c_10 = max(n_10, 0 - prices[i])
# c_11: n_01-prices[i] 持股0卖出1 到 持股1卖出1 【第一次结束的基础上第二次买】
c_11 = max(n_11, n_01-prices[i])
n_01, n_02, n_10, n_11 = c_01, c_02, c_10, c_11
return max(n_01, n_02, 0)