给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
示例:[1,2,3,0,2]
价格 p(i)\收益 dp[i] | i=0,p[0]=1 | i=1,p[1]=2 | i=2,p[2]=3 | … | i |
---|---|---|---|---|---|
持有 0 | 0-1 | max(0-1,0-2) | max(-1,0-3) | … | max(dp[i-1][0], dp[i-1][2] - p[i]) |
冷冻期 1 | - | 0-1+2 | -1+3 | … | dp[i-1][0]+p[i] |
不持有 2 | 0 | max(0,-) | max(0,1) | … | max(dp[i-1][2], dp[i-1][1]) |
最后如果计算收益最大,则结束时状态不能为持有
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length,
dp = Array(len)
// prices小于2是买入来不及卖出
if (len < 2) return 0
// 初始化存储对象
for (let i = 0; i < len; i++) {
dp[i] = [0, 0, 0]
}
// 初始化成本
dp[0][0] = -prices[0]
for (let i = 1; i < len; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2] - prices[i])
dp[i][1] = dp[i - 1][0] + prices[i]
dp[i][2] = Math.max(dp[i - 1][1], dp[i - 1][2])
}
return Math.max(dp[len - 1][1], dp[len - 1][2])
}
优化:
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length
// prices小于2是买入来不及卖出
if (len < 2) return 0
// 初始化存储对象
let A = -prices[0],
B = 0,
C = 0
// 初始化成本
for (let i = 1; i < len; i++) {
let a = Math.max(A, C - prices[i])
let b = A + prices[i]
let c = Math.max(B, C)
A = a
B = b
C = c
}
return Math.max(B, C)
}
可以归纳为:
持有:
第一天成本 -prices[0]
i=1 第二天持有,有两种可能(前一天不存在持有冷冻情况):
i 大于 1 持有时(前一天存在持有冷冻情况):
不持有:
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length
// prices小于2是买入来不及卖出
if (len < 2) return 0
let hold = Array(len),
unhold = Array(len)
// 初始化存储对象
hold[0] = -prices[0]
unhold[0] = 0
for (let i = 1; i < len; i++) {
if (i == 1) {
hold[i] = Math.max(-prices[0], -prices[1])
} else {
hold[i] = Math.max(hold[i - 1], unhold[i - 2] - prices[i], unhold[i - 1])
}
unhold[i] = Math.max(unhold[i - 1], hold[i - 1] + prices[i])
}
return unhold[len - 1]
}