JavaScript|LeetCode|动态规划|309. 最佳买卖股票时机含冷冻期

法1:动态规划
想法1:

  1. 第 i 天时,将 prices[i] 与 prices[j] (j < i) 比较,意思是:在第 j 天买入,第 i 天卖出(也可能是第 j 天正持有一只股票,而不是购入新股)。会有以下两种情况出现
  • prices[j] > prices[j - 1]:那么在第 j 天持有股票,或可以买入股票。
    d p [ i ] = M a t h . m a x ( d p [ i ] , d p [ j ] + p r i c e s [ i ] − p r i c e s [ j ] , d p [ j ] ) dp[i] = Math.max(dp[i], dp[j] + prices[i] - prices[j], dp[j]) dp[i]=Math.max(dp[i],dp[j]+prices[i]prices[j],dp[j])
    dp[i]:之前的交易方式可能得到了更大利润
    dp[j] + prices[i] - prices[j]:因为在第 j 天持有股票,或可以买入股票,所以可以用第 j 天的最大利润 + 从第 j 天到第 i 天的利润
    dp[j]:如果 prices[i] - prices[j] < 0,则在第 i 天不卖出可以得到的利润更多,即 dp[j]
  • prices[j] < prices[j - 1]:那么在第 j 天之前一定卖出了。
    d p [ i ] = M a t h . m a x ( d p [ i ] , d p [ j − 2 ] + p r i c e s [ i ] − p r i c e s [ j ] , d p [ j ] ) dp[i] = Math.max(dp[i], dp[j - 2] + prices[i] - prices[j], dp[j]) dp[i]=Math.max(dp[i],dp[j2]+prices[i]prices[j],dp[j])
    dp[i]:之前的交易方式可能得到了更大利润
    dp[j - 2] + prices[i] - prices[j]:第 j 天不是冷冻期,则在第 j - 2 天就卖出了,利润为 dp[j - 2],再加上从第 j 天到第 i 天的利润
    dp[j]:第 j 天是冷冻期,则在第 j - 1 天卖出了,利润为dp[j](因为第 j 天是冷冻期,所以第 j 天最大利润就是dp[j - 1])
  1. 因为会遍历到 j - 1 和 j - 2,为防止数组dp访问错误,对于 j 为 0 和1的情况要另外处理
/** 
* @param {number[]} prices 
* @return {number} 
*/
var maxProfit = function(prices) {    
    if(prices.length == 0) {        
        return 0;    
    }    
    var dp = [], i = 0, j = 0;    
    for(i = 0; i < prices.length; i++) {        
        dp[i] = 0;    
    }
    for(i = 0; i < prices.length; i++) {        
        for(j = 0; j < i; j++) {            
            if(j == 0) {                
                dp[i] = Math.max(dp[i], prices[i] - prices[j]);                
                continue;            
            }            
            if(j == 1) {                
                dp[i] = Math.max(dp[i], prices[i] - prices[j] + dp[j], dp[j]);                
                continue;            
            }

            if(prices[j] > prices[j - 1]) {                
                dp[i] = Math.max(dp[i], dp[j] + prices[i] - prices[j], dp[j]);            
            }            
            else {                
                dp[i] = Math.max(dp[i], dp[j - 2] + prices[i] - prices[j], dp[j]);            
            }        
        }    
    }    
    return dp[prices.length - 1];
};

想法2:
看了题解

  1. 对第 i 天进行分类:
  • 冷却 or 非冷却
  • 非冷却中:持股(包括买入) or 不持股(包括卖出)
  1. 冷却在卖出之后;卖出在买入之后;买入在冷却之后

具体看代码中的注释

/** 
* @param {number[]} prices 
* @return {number} 
*/
var maxProfit = function(prices) {    
    if(prices.length == 0) {        
        return 0;    
    }    
    // 给第 i 天进行分类:    
    // 1. 冷却 or 非冷却    
    //      C[i]表示第 i 天是冷却期的最大利润:第 i - 1 天卖出    
    // 2. 非冷却中:持股 or 不持股    
    //      持股:第 i 天买入,或继承前一天的股    
    //              B[i]表示第 i 天:MAX{买入, 有股的观望}    
    //      不持股:第 i 天卖出,或前一天也没有股            
    //              A[i]表示第 i 天:MAX{卖出, 没有股的观望}    

    var A = [], B = [], C = [], i = 0, N = prices.length;
    
    for(i = 0; i < N; i++) {        
        A[i] = B[i] = C[i] = 0;    
    }
    A[0] = 0, B[0] = -prices[0], C[0] = 0;
    
    for(i = 1; i < N; i++) {        
        // A[i - 1]:继续没有股的观望        
        // B[i - 1] + prices[i]:卖出(卖出在买入或有股的观望之后)        
        // 不考虑C[i - 1]:因为卖出在买入B[i - 1]之后;没有股的观望即继承A[i - 1]的状态        
        A[i] = Math.max(A[i - 1], B[i - 1] + prices[i]);
        
        // B[i - 1]:继续有股的观望        
        // C[i - 1] - prices[i]:在冷却期之后买入        
        // 不考虑A[i - 1]:因为卖出之后不能立马买入;没有股的观望之后的买入算入冷却期之后的买入        
        B[i] = Math.max(B[i - 1], C[i - 1] - prices[i]);
        
        // 冷却期在卖出之后        
        C[i] = A[i - 1];    
    }    

    // 最后一天:不持股或冷却(也是不持股)的状态可能得到最大利润    
    return Math.max(A[N - 1], C[N - 1]);
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值