法1:动态规划
想法:
- A[i]:第 i 天买入的最大利润;B[i]:第 i 天卖出的最大利润
- A[i][0] 表示在第 i 天 第 0 次买入
- B[i][0] 表示在第 i 天 第 0 次卖出
- 依次类推
- 第 0 次卖出 -> 第 1 次买入 -> 第 1 次卖出 -> 第 2 次买入 -> 第 2 次卖出
- 最大利润在:第 0 次卖出 / 第 1 次卖出 / 第 2 次卖出 时取得
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
if(prices.length == 0) {
return 0;
}
// A[i]:第 i 天买入的最大利润;B[i]:第 i 天卖出的最大利润
// 第 0 次卖出 -> 第 1 次买入 -> 第 1 次卖出 -> 第 2 次买入 -> 第 2 次卖出
// 最大利润在:第 0 次卖出 / 第 1 次卖出 / 第 2 次卖出 时取得
var i = 0, j = 0, A = [], B = [], N = prices.length;
for(i = 0; i < N; i++) { // 在第i天
A[i] = [];
B[i] = [];
// 第0 ~ 2次买入/卖出的最大利润
A[i][0] = 0;
A[i][1] = A[i][2] = -prices[i];
B[i][0] = B[i][1] = B[i][2] = 0;
}
for(i = 1; i < N; i++) { // 更新A[] B[]
for(j = 0; j < i; j++) { // 对于第 i 天之前的每一天
A[i][1] = Math.max(A[i][1], B[j][0] - prices[i], A[i - 1][1]);
// 在第 i 天进行第 1 次买入的最大利润:
// A[i][1]:之前存有的值更大
// B[j][0] - prices[i]:第 0 次卖出后的第 1 次买入(即第 1 次买入)
// 继承前一天的值(即持有之前天第 1 次买入的股票)
A[i][2] = Math.max(A[i][2], B[j][1] - prices[i], A[i - 1][2]);
B[i][1] = Math.max(B[i][1], A[j][1] + prices[i], B[i - 1][1]);
B[i][2] = Math.max(B[i][2], A[j][2] + prices[i], B[i - 1][2]);
}
}
return Math.max(B[N - 1][0], B[N - 1][1], B[N - 1][2]);
};
优化
看了题解
想法:
- 如果按照从第 0 天到第 prices.length - 1 天的顺序,依次访问各个股票的价格,则无需保存是哪一天的买入卖出;都是从 前些天 往 后些天 更新的
- 故只需要4个变量来保存:第一次买入、第一次卖出、第二次买入、第二次卖出 的最大利润,直到遍历完prices数组,第二次卖出的最大利润即为答案
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
var firstBuy = -prices[0], firstSell = 0,
secondBuy = -prices[0], secondSell = 0,
i = 0, N = prices.length;
for(i = 1; i < N; i++) {
if(secondSell < secondBuy + prices[i]) { // 更新secondSell
secondSell = secondBuy + prices[i];
}
if(secondBuy < firstSell - prices[i]) { // 更新secondBuy
secondBuy = firstSell - prices[i];
}
if(firstSell < firstBuy + prices[i]) { // 更新firstSell
firstSell = firstBuy + prices[i];
}
if(firstBuy < -prices[i]) { // 更新firstBuy
firstBuy = -prices[i];
}
}
return secondSell;
};