JavaScript|LeetCode|动态规划|123. 买卖股票的最佳时机 III

法1:动态规划
想法:

  1. A[i]:第 i 天买入的最大利润;B[i]:第 i 天卖出的最大利润
  • A[i][0] 表示在第 i 天 第 0 次买入
  • B[i][0] 表示在第 i 天 第 0 次卖出
  • 依次类推
  1. 第 0 次卖出 -> 第 1 次买入 -> 第 1 次卖出 -> 第 2 次买入 -> 第 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]);
};

优化
看了题解
想法:

  1. 如果按照从第 0 天到第 prices.length - 1 天的顺序,依次访问各个股票的价格,则无需保存是哪一天的买入卖出;都是从 前些天 往 后些天 更新的
  2. 故只需要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;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值