leetcode 123 買賣股票的最佳時機 III

溫酒煮Bug發表於2019-01-29

描述:

給定一個陣列,它的第 i 個元素是一支給定的股票在第 i 天的價格。

設計一個演算法來計算你所能獲取的最大利潤。你最多可以完成 兩筆 交易。

注意: 你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

示例 1:

輸入: [3,3,5,0,0,3,1,4]
輸出: 6
解釋: 在第 4 天(股票價格 = 0)的時候買入,在第 6 天(股票價格 = 3)的時候賣出,
這筆交易所能獲得利潤 = 3-0 = 3 。
     隨後,在第 7 天(股票價格 = 1)的時候買入,在第 8 天 (股票價格 = 4)的時候賣出,
這筆交易所能獲得利潤 = 4-1 = 3 。複製程式碼

示例 2:

輸入: [1,2,3,4,5]
輸出: 4
解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接連購買股票,之後再將它們賣出。   
     因為這樣屬於同時參與了多筆交易,你必須在再次購買前出售掉之前的股票。
複製程式碼

示例 3:

輸入: [7,6,4,3,1] 
輸出: 0 
解釋: 在這個情況下, 沒有交易完成, 所以最大利潤為 0。複製程式碼

思路:

這是一個經典的動態規劃問題,解決動態規劃問題的步驟是:

  • 分析出dp定義
  • 列出dp方程

dp定義的分析思路是,思考 i 狀態的產生,和 i - 1狀態有什麼關係,也就是說 i 的狀態,受 i - 1的哪些維度的影響。這裡股票的收益,受前一天股價、是否持股、交易次數有關。所以我們, 可以抽象出三個維度來解決這個問題,即:

dp[ i ][ j ][ k ]:i是天數,j是交易的次數,k是是否持股,我們用這個三維陣列來記錄狀態即可,陣列中存的值,就是當天該狀態下的最大收益。

dp方程需要根據j的取值來分組,即當j = 0 時,不存在 j - 1時的狀態。

當j == 0的時候:

即之前沒有過股票交易,所以是否持股和交易次數都和前一天的狀態相同。

  • dp[i][j][0] = Math.max(dp[i - 1][j][0], 0);
  • dp[i][j][1] = Math.max(dp[i - 1][j][1], 0);

當j != 0 的時候:

如dp[i][j][0] 第i天,交易了j次,不持股,前一天有兩個狀態可以轉移到該狀態,即:

  1. 前一天交易了j次,不持股
  2. 前一天交易了j次,持股但是賣掉了。
  • dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
  • dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);

程式碼:

class Solution {
  public int maxProfit(int[] prices) {
    if(prices.length == 0) return 0;  
    int[][][] dp = new int[prices.length][3][2];
    dp[0][1][1] = 0 - prices[0];
    dp[0][2][1] = 0 - prices[0];
    int max = 0;
    for (int i = 1; i < prices.length; i++) {
      for (int j = 0; j < 3; j++) {
        if (j == 0) {
          dp[i][j][0] = Math.max(dp[i - 1][j][0], 0);
          dp[i][j][1] = Math.max(dp[i - 1][j][1], 0);
        } else {
          dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
          dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
        }
      }
    }
    for (int i = 0; i < prices.length; i++) {
      max = Math.max(max, dp[i][2][0]);
    }
    return max;
  }
}
複製程式碼

結果:

leetcode 123 買賣股票的最佳時機 III



相關文章