阅读目录
- 1. 题目
- 2.解题思路
- 3. 代码实现
1. 题目
2.解题思路
根据题意,每一天有这样几个状态:买入股票、卖出股票、冷冻期、持有股票,因此,我们假设 f
为每天这几个状态下对应的最大收益,由于持有股票时不知道是哪天买入的,所以我们还需要知道当天状态是持有股票时的买入股票价格。因此有:
f [ 0 ] = 当天买入股票后的最大收益 f [ 1 ] = 当天卖出股票后的最大收益 f [ 2 ] = 当天是冷冻期的最大收益 f [ 3 ] = 当天继续持有股票的最大收益 f [ 4 ] = 当天持有股票的买入价格 f[0] = 当天买入股票后的最大收益 \\ f[1] = 当天卖出股票后的最大收益 \\ f[2] = 当天是冷冻期的最大收益 \\ f[3] = 当天继续持有股票的最大收益 \\ f[4] = 当天持有股票的买入价格 \\ f[0]=当天买入股票后的最大收益f[1]=当天卖出股票后的最大收益f[2]=当天是冷冻期的最大收益f[3]=当天继续持有股票的最大收益f[4]=当天持有股票的买入价格
状态转移时,
第 i − 1 i-1 i−1 天是冷冻期,第 i i i 天才可以买入,所以有 f [ i ] [ 0 ] = f [ i − 1 ] [ 2 ] f[i][0]=f[i-1][2] f[i][0]=f[i−1][2]。
第 i − 1 i-1 i−1 天是买入股票或者持有股票,第 i i i 天才可以卖出,状态是二者的较大值,所以有 f [ i ] [ 1 ] = m a x ( f [ i − 1 ] [ 0 ] + p r i c e s [ i ] − p r i c e s [ i − 1 ] , f [ i − 1 ] [ 3 ] + p r i c e s [ i ] − f [ i − 1 ] [ 4 ] ) f[i][1]=max(f[i-1][0] + prices[i] - prices[i-1], f[i-1][3] + prices[i] - f[i-1][4]) f[i][1]=max(f[i−1][0]+prices[i]−prices[i−1],f[i−1][3]+prices[i]−f[i−1][4])。
第 i − 1 i-1 i−1 天是卖出或者冷冻期,第 i i i 天才可以是冷冻期,所以有 f [ i ] [ 2 ] = m a x ( f [ i − 1 ] [ 2 ] , f [ i − 1 ] [ 1 ] ) f[i][2]=max(f[i-1][2], f[i-1][1]) f[i][2]=max(f[i−1][2],f[i−1][1])。
第 i − 1 i-1 i−1 天是买入或者持有,第 i i i 天才可以是持有,这时候,我们需要比较是买入-持有获得的价值大还是持有-持有获得的价值大,前者的价值是 f [ i − 1 ] [ 0 ] − p r i c e s [ i − 1 ] f[i-1][0] - prices[i-1] f[i−1][0]−prices[i−1],后者的价值是 f [ i − 1 ] [ 3 ] − f [ i − 1 ] [ 4 ] f[i-1][3] - f[i-1][4] f[i−1][3]−f[i−1][4]。如果前者的价值大,则更新 f [ i ] [ 3 ] = f [ i − 1 ] [ 0 ] , f [ i ] [ 4 ] = p r i c e s [ i − 1 ] f[i][3]=f[i-1][0],f[i][4]=prices[i-1] f[i][3]=f[i−1][0],f[i][4]=prices[i−1],如果后者的价值大,则更新 f [ i ] [ 3 ] = f [ i − 1 ] [ 3 ] , f [ i ] [ 4 ] = f [ i − 1 ] [ 4 ] f[i][3]=f[i-1][3],f[i][4]=f[i-1][4] f[i][3]=f[i−1][3],f[i][4]=f[i−1][4]。
3. 代码实现
class Solution:def maxProfit(self, prices: List[int]) -> int:if len(prices) == 1:return 0ret = 0# dp[0] 代表当天买入股票后的最大收益# dp[1] 代表当天卖出股票后的最大收益# dp[2] 代表当天是冷冻期的最大收益# dp[3] 代表当天是持有股票后的最大收益# dp[4] 代表当天是持有股票,买入的股票价格dp = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]dp[1][1] = prices[1] - prices[0]dp[1][4] = prices[0]ret = max(ret, dp[1][1])for i in range(2, len(prices)):dp.append([0, 0, 0, 0, 0])dp[i][0] = dp[i -1][2]dp[i][1] = max(prices[i] - prices[i-1] + dp[i-1][0],prices[i] - dp[i-1][4] + dp[i-1][3])ret = max(ret, dp[i][1])dp[i][2] = max(dp[i-1][1], dp[i-1][2])buy_hold = dp[i-1][0] - prices[i-1]hold_hold = dp[i-1][3] - dp[i-1][4]if buy_hold > hold_hold:dp[i][3] = dp[i-1][0]dp[i][4] = prices[i-1]else:dp[i][3] = dp[i-1][3]dp[i][4] = dp[i-1][4]return ret
注意,如果初始化 d p = [ [ 0 , 0 , 0 , 0 , 0 ] ] ∗ l e n ( p r i c e s ) dp = [[0, 0, 0, 0, 0]] * len(prices) dp=[[0,0,0,0,0]]∗len(prices),那么 d p dp dp 中所有的列表都是同一个,修改一个所有的都会跟着变动。