本文主題是講動態規劃,涉及題目近40題,每題超過3種方法解決,共100多種寫法,思路和目錄結構**於收藏夾中的乙個課程grokking dynamic programming patterns for coding interviews,其中grok是深刻領會,深入掌握的意思,我翻譯成暢遊,加上自己的理解,消化(擷取的課程的目錄),得到本文,文章很長,其實人生的路也很長,是吧?
動態規劃(dp)是一種求解優化問題的演算法,它將問題分解為更簡單的子問題,並利用整體問題的最優解取決於子問題的最優解這一事實看個例子斐波那契數列,眾所周知,斐波那契數列是一系列的數字,其中每個數字都是前面兩個數字的和,前幾個斐波那契數列是0、1、1、2、3、5和8,以此類推。
如果我們要求計算第n個斐波那契數列,我們可以用下面的方程來做:
fib
(n)=
fib(n-1)
+fib
(n-2),
for n >
1
我們可以清楚地看到,為了解決整個問題(即fib(n)
),我們將其分解為兩個更小的子問題(fib(n-1)
和fib(n-2)
)。這說明我們可以用dp來解決這個問題
在理解dp問題的不同方法之前,讓我們先看看乙個問題的哪些特徵告訴我們可以應用dp來解決它。
子問題是原始問題的更小粒度。如果找到它的解決方案涉及到多次解決相同的子問題,那麼任何問題都有重疊的子問題。以斐波那契數列為例,為了找到fib(4)
,我們需要將其分解為以下子問題:
[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-qfdxekam-1614862697542)(d:\dev\srccode\geek-algorithm-leetcode\src\main\leetcode_manuscripts\summary\暢遊面試中的動態規劃模式.assets\image-20210303191922492.png)]
我們可以清楚地看到重疊的子問題模式,因為fib(2)
已經計算了兩次,fib(1)
已經計算了三次。
如果它的整體最優解可以由其子問題的最優解構造出來,那麼任何問題都具有最優子結構性質。對於斐波那契數列,我們知道
fib
(n)=
fib(n-1)
+fib
(n-2
)
這清楚地表明大小為n
的問題已經被簡化為大小為n-1
和n-2
的子問題。因此,斐波那契數具有最優子結構性質。
dp問題一般有兩種方式去解決2.1.自頂向下記憶化(top-down)
在這種方法中,我們試圖通過遞迴地找到較小子問題的解決方案來解決較大的問題。每當我們解決乙個子問題時,對子問題的結果快取起來,這樣當它被多次呼叫時,我們就不會重複地解決它。相反,我們可以只返回儲存的結果。這種儲存已經解決的子問題的結果的技術叫做記憶化。
我們將在斐波那契數列的例子中看到這種技術。首先,讓我們看看尋找第n
個斐波那契數列的非dp
遞迴解:
class
fibonacci
public
static
void
main
(string[
] args)
}
output
5th fibonacci is --
->
56th fibonacci is --
->
87th fibonacci is --
->
13
正如我們上面所看到的,這個問題顯示了重疊子問題模式,所以讓我們在這裡利用記憶。我們可以使用乙個陣列來儲存已經解決的子問題(請參閱高亮顯示的行中的更改)。
class
fibonacci
public
intcalculatefibonaccirecursive
(int
memoize,
int n)
public
static
void
main
(string[
] args)
}
2.2.自底向上填表(bottom-up)
填表與自頂向下方法相反,避免了遞迴。在這種方法中,我們自底向上地解決問題(即首先解決所有相關的子問題)。這通常通過填充乙個n
維表來完成。根據表中的結果,然後計算頂部/原始問題的解決方案。
填表與記憶化是相反的,因為在記憶化中,我們解決問題,並維護已經解決的子問題的對映。換句話說,在記憶化中,我們從上到下,也就是說我們先解決最上面的問題(通常遞迴下來解決子問題)。
讓我們將填表應用到我們的斐波那契數列的例子中。因為我們知道每個斐波那契數都是前面兩個數的和,所以我們可以使用這個事實來填充我們的表。
下面是自底向上動態規劃的**:
class
fibonacci
public
static
void
main
(string[
] args)
}
我們將始終從乙個暴力遞迴解決方案開始,這是開始解決任何dp問題的最佳方式。一旦我們有了遞迴的解決方案,我們就會應用記憶化和填表。
讓我們應用這些知識來解決一些常見的dp問題。
動態規劃套路秒殺揹包問題
給你乙個可裝載重量為w的揹包和n個物品,每個物品有重量和價值兩個屬性。其中第i個物品的重量為wt i 價值為val i 現在讓你用這個揹包裝物品,最多能裝的價值是多少?舉個簡單的例子,輸入如下 n 3,w 4 wt 2,1,3 val 4,2,3 演算法返回 6,選擇前兩件物品裝進揹包,總重量 3 ...
leetcode中的動態規劃
1186.刪除一次得到子陣列最大和 描述 給你乙個整數陣列,返回它的某個 非空 子陣列 連續元素 在執行一次可選的刪除操作後,所能得到的最大元素總和。換句話說,你可以從原陣列中選出乙個子陣列,並可以決定要不要從中刪除乙個元素 只能刪一次哦 刪除後 子陣列中至少應當有乙個元素,然後該子陣列 剩下 的元...
面試準備(一) 動態規劃
動態規劃的思路說起來很簡單,但是新遇到乙個題目往往就會卡殼,甚至出現解不出來的情況。因此學習的過程中,有必要對面試準備中涉及到的動態規劃題目記錄,這裡只談思路,不涉及具體實現。通過分析不僅可以總結思路,更重要的是能從這些問題中找出動態規劃題目求解的共性,希望徹底搞定動態規劃!動態規劃常用來解決優化問...