步骤一、确定状态:
确定dp数组及下标含义
dp[i] 表示的是在第i天可以获取的最大利润,每天会有持有股票和不持有 股票两种状态,这个是第二维度,还是用0和1表示。 而对于每一种状态, 这里还会有交易次数的记录k次, 这个是第三维度。所以dp[天数][当前是 否持股][卖出的次数]
步骤二、推断状态方程:
未持有股票的状态 dp[i][0][k]系列 如果k=0的话,那么还是dp[i][0][0]等于0,开始的状态
如果k>0的话, 未持有表示要么延续之前的状态,要么是当天卖了出去 延续之前的状态, 即dp[i-1][0][k] 当天卖了出去,说明前一天是持有股票的, 即dp[i-1][1][k-1]+prices[i] 这里取最大就是 dp[i][0][k]=max(dp[i-1][0][k], dp[i-1][1][k-1]+prices[i])
持有股票的状态dp[i][1][k]系列
如果k=0的话, 说明是第一次买入的状态, 此时利润要么是延续之前的,要么 是今天刚买的
延续之前的, 即dp[i-1][1][0]
今天刚买的, 即昨天是没有股票的, dp[i-1][0][0]-prices[i]
所以这里取最大是dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][0][0]-prices[i])
如果k>0,也是这个思路, dp[i][1][k-1] = max(dp[i-1][1][k-1], dp[i-1][0][k- 1]-prices[i])
同样的,等于k取不到,因为这时候已经完成了K笔交易,不能再买了。 dp[i][1][k]=float("-inf")
步骤三、规定初始条件:
初始条件:
全局初始化为0, 然后第0天的所有状态必须都初始化出来: dp[0][0][0] = 0: 开始啥也没干, 利润0;
dp[0][1][0] = -prices[0]: 第0天持有股票,且进行了0次 交易,这是第一次买入,利润-prices[0]
步骤四、计算顺序:
遍历方式会是两层循环了,首先会从1到len(prices)遍历天, 然后再从1到k遍历交易次数,正向遍历
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
if len(prices) < 2 or k == 0:
return 0
# dp[天数][当前是否持股][卖出的次数]
dp = [[[0 for _ in range(k+1)] for _ in range(2)] for _ in range(len(prices))]
# 初始化
dp[0][0][0], dp[0][1][0] = 0, -prices[0]
for i in range(1, k):
dp[0][0][i], dp[0][1][i] = float("-inf"), float("-inf") # 第一天完不成交易
# 遍历
for i in range(1, len(prices)):
for k in range(1, k+1):
dp[i][0][k] = max(dp[i-1][0][k], dp[i-1][1][k-1] + prices[i])
dp[i][1][k-1] = max(dp[i-1][1][k-1], dp[i-1][0][k-1] - prices[i])
# 最后一天不持有股票的值
return max(dp[-1][0])