题目链接
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/
题目描述
给定价格数组prices,prices[i]表示一支给定股票第i天的价格。不限定交易次数,但在再次购买前必须出售之前的股票。并且卖出股票后无法在第二天买入股票。(即冷冻期为一天),设计算法来计算能够获得的最大利润。
示例
输入:[1,2,3,0,2]
输出:3
i从0开始计数,从第0天(价格为1)买入,第1天(价格为2)卖出。第3天(价格为0)买入,第4天(价格为2)卖出。
解题思路一
此题在【leetcode-Python】-Dynamic Programming -122. Best Time to Buy and Sell Stock II上增加了冷冻期的约束。可以同样设置由dp[i][0]表示第i天结束后未持股状态的最大利润,由dp[i][1]表示第i天结束后持股状态的最大利润。
其中dp[i][1]包含两种情况:
(1)第i-1天持股,第i天无操作;
(2)第i-2天未持股,第i天买入。(由于设有冷冻期,因此第i天买入需要从第i-2天未持股的状态开始转移)。
Python实现
class Solution:
def maxProfit(self, prices: List[int]) -> int:
#第0天不持股和第0天持股
dp_0 = 0
dp_1 = -prices[0]
#暂存两天前未持股状态下的最大收益
dp_2days_before = 0 #初始化为0,在第0天之前未持股,收益自然为0
#-float('inf')
for i in range(1,len(prices)):
tmp = dp_0 #tmp存储第i-1天未持股的最大收益
dp_0 = max(dp_0,dp_1 + prices[i]) #第i天不持股
dp_1 = max(dp_1,dp_2days_before - prices[i]) #从前两天且未持股的状态中转移过来
dp_2days_before = tmp #tmp赋值给dp_2days_before,在下一轮第i+1天的更新中dp_2days_before存储第i-1天未持股的最大收益。
return dp_0
除了先把第一天的状态作为base case写出来,还有还有一种初始化方式:
在买卖股票问题中,一般将未持股状态的最大利润都初始化为0,持股状态的最大利润都初始化为负无穷。因为后续还未更新,由于需要买入股票,持股状态时的最大利润有可能是负的,因此需要用负无穷来兜底(即使是负值,也能是较大的那个)。然后遍历更新天数时从第0天就开始更新(for循环中i从0开始计)。代码如下:
class Solution:
def maxProfit(self, prices: List[int]) -> int:
#初始化
dp_0 = 0
dp_1 = -float('inf')
dp_2days_before = 0
#i从0开始更新
for i in range(len(prices)):
tmp = dp_0
dp_0 = max(dp_0,dp_1 + prices[i])
dp_1 = max(dp_1,dp_2days_before - prices[i])
dp_2days_before = tmp
return dp_0
时间复杂度与空间复杂度
时间复杂度为O(N),空间复杂度为O(1)。