動態規劃難?讀完這篇還不理解那就不要請我吃雞了

zy445566發表於2018-12-20

昨天同事說動態規劃很難,我說不會啊,理解了就很簡單,我同事表示不屑,以為我在炫技。於是乎我問了一個工作六年的前同事,他居然也覺得高大上,並且表示接觸過會動態規劃的朋友,覺得很牛逼。

我了個天,表示震驚了,簡直嚇的我瑟瑟發抖發抖好麼。既然如此,那我一定要讓大家理解,讓大家也牛逼牛逼。

以題舉例

以中國leetcode(力扣)的121道題《買賣股票的最佳時機》舉例,題目如下:

給定一個陣列,它的第 i 個元素是一支給定股票第 i 天的價格。如果你最多隻允許完成一筆交易(即買入和賣出一支股票),設計一個演算法來計算你所能獲取的最大利潤。注意你不能在買入股票前賣出股票。示例 1:輸入: [7,1,5,3,6,4]輸出: 5解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。注意利潤不能是 7-1 = 6, 因為賣出價格需要大於買入價格。示例 2:輸入: [7,6,4,3,1]輸出: 0解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。複製程式碼

首先說明一點,在這道題動態規劃並不算是高效的演算法,這道題即使是暴力法也能比動態規劃法要快一些,但本文是為了講動態規劃才講這道題的,而非為了這道題講動態規劃的。純粹是這道題講動態規劃更簡單。

不瞭解動態規劃的朋友可能不知道,動態規劃幾乎都是存在套路的,步驟如下:

  1. 將問題拆解成單一問題製表
  2. 根據表中結果進行求解

第一步:將問題拆解成單一問題製表

這是動態規劃的重中之重,拆的好壞基本決定你動態規劃寫的好壞,動態規劃更是一種思想。

這道題就很簡單了,我們可以把這個問題,先拆成單一問題,即如果我在這天買入,在哪天賣出最高?我們按題目中的示例 1舉例,價格陣列為[7,1,5,3,6,4]。

比如我在第一天買入,在哪天賣出最高呢?我們可以得到這樣一張表(不能交易標記X):

買入時間 買入價格 單天價格 7 1 5 3 6 4
賣出時間 第一天 第二天 第三天 第四天 第五天 第六天
第一天 7 獲利程度 X -6 -2 -4 -1 -3

填表原因如下:

  • 即因為你是第一天買入的,所以第一天不能交易,所以填X
  • 我們第一天買入的,買入價格為7,第二天值1,所以我們賣出則賺了-6.
  • 我們第一天買入的,買入價格為7,第三天值5,所以我們賣出則賺了-2.
  • 我們第一天買入的,買入價格為7,第四天值3,所以我們賣出則賺了-4.
  • 我們第一天買入的,買入價格為7,第五天值6,所以我們賣出則賺了-1.
  • 我們第一天買入的,買入價格為7,第六天值4,所以我們賣出則賺了-3.

有人說這個不是暴力解法麼?額,這道題的動態規劃的製表過程確實有點像。

那麼根據以上規則,如果我們是第二天買入的話,這個表格是不是就是這樣的。

買入時間 買入價格 單天價格 7 1 5 3 6 4
賣出時間 第一天 第二天 第三天 第四天 第五天 第六天
第二天 1 獲利程度 X X 4 2 5 3

那麼我合併這兩張表是不是就是這樣的:

買入時間 買入價格 單天價格 7 1 5 3 6 4
賣出時間 第一天 第二天 第三天 第四天 第五天 第六天
第一天 7 獲利程度 X -6 -2 -4 -1 -3
第二天 1 獲利程度 X X 4 2 5 3

那麼我們把這張表弄完整,即把第三天到第五天的買入,那是不是就是這樣的。

買入時間 買入價格 單天價格 7 1 5 3 6 4
賣出時間 第一天 第二天 第三天 第四天 第五天 第六天
第一天 7 獲利程度 X -6 -2 -4 -1 -3
第二天 1 獲利程度 X X 4 2 5 3
第三天 5 獲利程度 X X X -2 1 -1
第四天 3 獲利程度 X X X X 3 1
第五天 6 獲利程度 X X X X X -2
第六天 4 獲利程度 X X X X X X

因為第六天買了的話,已經是最後一天了,所以沒辦法賣了,所以全是X。

第二步:根據表中結果進行求解

上一步,已經把如果是某天買的,每天的獲利情況列了一遍,就是拆解成了單一問題。

那麼看最大利潤,很容易就能看出來了,就看那個數字最大就好了。

買入時間 買入價格 單天價格 7 1 5 3 6 4
賣出時間 第一天 第二天 第三天 第四天 第五天 第六天
第一天 7 獲利程度 X -6 -2 -4 -1 -3
第二天 1 獲利程度 X X 4 2 5⃣️ 3
第三天 5 獲利程度 X X X -2 1 -1
第四天 3 獲利程度 X X X X 3 1
第五天 6 獲利程度 X X X X X -2
第六天 4 獲利程度 X X X X X X

沒錯emoji的5的就是,那麼我們只要簡單的遍歷一下這個表是不是就能把結果取出來了?嗯,對的

最後

但一般來說動態規劃的題目不是這麼簡單的,通常在製表的時候會涉及一個疊加問題,在根據表計算結果一般也不是簡單的遍歷就能完成的,但理解動態規劃思想應該是沒什麼問題了。

個人認為動態規劃雖然效能不強,但是能把問題變得很直觀,讓人更簡單的解決問題。同時演算法的雜合度不高,很方便使用分散式為問題的每個單一問題進行求解。

本題程式碼:best-time-to-buy-and-sell-stock.js

來源:https://juejin.im/post/5c1b093a6fb9a049f57118b2

相關文章