暢遊面試中的動態規劃套路

2021-10-21 02:23:44 字數 3036 閱讀 3154

本文主題是講動態規劃,涉及題目近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-1n-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.刪除一次得到子陣列最大和 描述 給你乙個整數陣列,返回它的某個 非空 子陣列 連續元素 在執行一次可選的刪除操作後,所能得到的最大元素總和。換句話說,你可以從原陣列中選出乙個子陣列,並可以決定要不要從中刪除乙個元素 只能刪一次哦 刪除後 子陣列中至少應當有乙個元素,然後該子陣列 剩下 的元...

面試準備(一) 動態規劃

動態規劃的思路說起來很簡單,但是新遇到乙個題目往往就會卡殼,甚至出現解不出來的情況。因此學習的過程中,有必要對面試準備中涉及到的動態規劃題目記錄,這裡只談思路,不涉及具體實現。通過分析不僅可以總結思路,更重要的是能從這些問題中找出動態規劃題目求解的共性,希望徹底搞定動態規劃!動態規劃常用來解決優化問...