# [309] 最佳买卖股票时机含冷冻期
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
经典的多状态动态规划问题。可以分解为三种状态:
buy状态转移方程:buy[i] = max(cooldown[i-1] - prices[i], buy[i-1])
cooldown状态转移方程:cooldown[i] = max(sell[i-1], cooldown[i-1])
sell状态转移方程:sell[i] = max(buy[i-1] + prices[i], sell[i-1])
var maxProfit = function(prices) {
if (!prices || prices.length <= 1) return 0;
const buy = [];
buy[0] = -prices[0];
const sell = [];
sell[0] = 0;
const cooldown = [];
cooldown[0] = 0;
for (let i = 1; i < prices.length; i++) {
buy[i] = Math.max(cooldown[i - 1] - prices[i], buy[i - 1]);
cooldown[i] = Math.max(sell[i - 1], cooldown[i - 1]);
sell[i] = Math.max(buy[i - 1] + prices[i], sell[i - 1]);
}
return Math.max(sell[prices.length - 1], cooldown[prices.length - 1]);
};
由于cooldown状态并不会对最终的获利产生任何影响,因此可以将cooldown的状态归并进buy状态中。由于卖出后面一定需要跟一个cooldown状态,因此cooldown[i-1] = sell[i-2]
buy状态转移方程:buy[i] = max(buy[i-1], sell[i-2] - prices[i])
sell状态转移方程:sell[i] = max(sell[i-1], buy[i-1] + prices[i])
可以分解为两种状态,一个是当天执行买入操作所能获取的最大利润buy
当天状态为buy时: 由于sell后有一天的cd,金额为:两天前sell操作后的剩余金额 - 当天货物价格
当天状态不为buy(即为cd)时,金额等于一天前执行buy操作后的金额 两种情况取最大值
一个是当天执行卖出操作所能获取的最大利润sell
当天状态为sell时: 金额为:一天前buy操作后的剩余金额 + 当天货物价格
当天状态不为sell(即为cd)时,金额等于一天前执行sell操作后的金额
两种情况取最大值
var maxProfit = function(prices) {
if (!prices || prices.length <= 1) return 0;
const buy = [-prices[0], Math.max(-prices[0], -prices[1])];
const sell = [0, Math.max(prices[1] - prices[0], 0)];
for (let i = 2; i < prices.length; i++) {
buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]);
sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);
}
return sell[prices.length - 1];
};
由于该题状态转移方程只依赖dp[i-1]和dp[i-2],因此也可以用两个临时变量存储,从而优化空间复杂度为O(1),就不在此实现了。