昨天同事說動態規劃很難,我說不會啊,理解了就很簡單,我同事表示不屑,覺得我在炫技。因而乎我問了一個工做六年的前同事,他竟然也以爲高大上,而且表示接觸過會動態規劃的朋友,以爲很牛逼。git
我了個天,表示震驚了,簡直嚇的我瑟瑟發抖發抖好麼。既然如此,那我必定要讓你們理解,讓你們也牛逼牛逼。github
以中國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。
複製代碼
首先說明一點,在這道題動態規劃並不算是高效的算法,這道題即便是暴力法也能比動態規劃法要快一些,但本文是爲了講動態規劃纔講這道題的,而非爲了這道題講動態規劃的。純粹是這道題講動態規劃更簡單。數組
不瞭解動態規劃的朋友可能不知道,動態規劃幾乎都是存在套路的,步驟以下:bash
這是動態規劃的重中之重,拆的好壞基本決定你動態規劃寫的好壞,動態規劃更是一種思想。分佈式
這道題就很簡單了,咱們能夠把這個問題,先拆成單一問題,即若是我在這天買入,在哪天賣出最高?
咱們按題目中的示例 1舉例,價格數組爲[7,1,5,3,6,4]。性能
好比我在第一天買入,在哪天賣出最高呢?咱們能夠獲得這樣一張表(不能交易標記X):spa
買入時間 | 買入價格 | 單天價格 | 7 | 1 | 5 | 3 | 6 | 4 |
---|---|---|---|---|---|---|---|---|
-- | -- | 賣出時間 | 第一天 | 次日 | 第三天 | 第四天 | 第五天 | 第六天 |
第一天 | 7 | 獲利程度 | X | -6 | -2 | -4 | -1 | -3 |
填表緣由以下:設計
有人說這個不是暴力解法麼?額,這道題的動態規劃的製表過程確實有點像。
code
那麼根據以上規則,若是咱們是次日買入的話,這個表格是否是就是這樣的。
買入時間 | 買入價格 | 單天價格 | 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的就是,那麼咱們只要簡單的遍歷一下這個表是否是就能把結果取出來了?嗯,對的
但通常來講動態規劃的題目不是這麼簡單的,一般在製表的時候會涉及一個疊加問題,在根據表計算結果通常也不是簡單的遍歷就能完成的,但理解動態規劃思想應該是沒什麼問題了。
我的認爲動態規劃雖然性能不強,可是能把問題變得很直觀,讓人更簡單的解決問題。同時算法的雜合度不高,很方便使用分佈式爲問題的每一個單一問題進行求解。