1. 程式人生 > >[Leetcode309] 最佳買賣股票時機含冷凍期 動態規劃

[Leetcode309] 最佳買賣股票時機含冷凍期 動態規劃

cool down 時機 最大的 轉移 變量存儲 leet e30 and

題目:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

思路:

  這題一看就是動態規劃。把prices數組掃一遍,每天無非4種情況:買入、賣出、冷凍、啥也不幹。冷凍期其實也可以視作一種操作。我們要考慮的就是,截至到今天,我的最後一次操作是買、賣還是冷凍時,我到今天的收益最高。於是可以開三個數組buy[]、sell[]、lock[],buy[i]表示截至第i天,最後一次操作是買入的話,最大的收益是多少。sell[i]和lock[]同理。

  於是不難列出狀態轉移方程:

  // 其中buy[i-1]表示截至昨天最後一個操作是買入且今天啥也不幹,lock[i-1] - prices[i]表示截至昨天最後一個操作是冷凍且今天買入

  buy[i] = max{ buy[i-1] , lock[i-1] - prices[i] } 特殊地,buy[0] = -prices[0]

  // buy[i-1] + prices[i]表示截至昨天最後一個操作是買入且今天賣出

  sell[i] = buy[i-1] + prices[i]

  // 其中lock[i-1]表示截至昨天最後一個操作是冷凍且今天啥也不幹,sell[i-1]表示截至昨天最後一個操作是賣出且今天冷凍

  lock[i] = max { lock[i-1] , sell[i-1] }

代碼:

  

 1 /**
 2  * @author
yuan 3 * @version 0.1 4 * @date 2019/4/5 5 */ 6 public class Leetcode309 { 7 8 public int maxProfit(int[] prices) { 9 if (prices.length == 0) { 10 return 0; 11 } 12 int[] buy = new int[prices.length]; 13 int[] sell = new int[prices.length];
14 int[] lock = new int[prices.length]; 15 for (int i = 0; i < prices.length; i++) { 16 buy[i] = Integer.MIN_VALUE; 17 } 18 for (int i = 0; i < prices.length; i++) { 19 if (i == 0) { 20 buy[i] = -prices[i]; 21 } else { 22 buy[i] = Math.max(buy[i - 1], lock[i - 1] - prices[i]); 23 sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]); 24 lock[i] = Math.max(lock[i - 1], sell[i - 1]); 25 } 26 } 27 int result = buy[prices.length - 1]; 28 if (sell[prices.length - 1] > result) { 29 result = sell[prices.length - 1]; 30 } 31 if (lock[prices.length - 1] > result) { 32 result = lock[prices.length - 1]; 33 } 34 return result; 35 } 36 }

優化:

  對於每一天的情況,只有上一天的狀態對今天有用,因此三個數組可以縮減到長度為2。也可以只用一個變量存儲,但在賦值前要註意用臨時變量保存一下。

[Leetcode309] 最佳買賣股票時機含冷凍期 動態規劃