LeetCode刷題 動態規劃(五)

2021-10-14 05:07:56 字數 3863 閱讀 4270

上一節總結了 0-1揹包,接著總結 完全揹包。在做題中總結套路,事半功倍!

引入322,零錢兌換,medium

518,零錢兌換ⅱ,medium

377,組合總和ⅳ,medium

139,單詞拆分,medium

完全揹包問題總結 引入

完全揹包的變體問題:物品可以無限次選取,且考慮物品放入的順序

下面在具體題目中進行總結。

322,零錢兌換,medium

給定不同面額的硬幣 coins 和乙個總金額 amount。編寫乙個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。

你可以認為每種硬幣的數量是無限的。

示例 1:

輸入:coins = [1, 2, 5], amount = 11

輸出:3

解釋:11 = 5 + 5 + 1

示例 2:

輸入:coins = [2], amount = 3

輸出:-1

示例 3:

輸入:coins = [1], amount = 0

輸出:0

示例 4:

輸入:coins = [1], amount = 1

輸出:1

示例 5:

輸入:coins = [1], amount = 2

輸出:2

1 <=coins.length<= 12

1 <=coins[i]<= 231 - 1

0 <=amount<= 104

解法一:二維(先遍歷物品,再遍歷揹包)

**:

class

solution

for(

int i =

1; i < n +

1; i++)}

return dp[n]

[amount]

> amount ?-1

: dp[n]

[amount];}

}

狀態壓縮:

class

solution

}return dp[amount]

> amount ?-1

: dp[amount];}

}

解法二:一維(先遍歷揹包,再遍歷物品)

518,零錢兌換ⅱ,medium

給定不同面額的硬幣和乙個總金額。寫出函式來計算可以湊成總金額的硬幣組合數。假設每一種面額的硬幣有無限個。

示例 1:

輸入: amount = 5, coins = [1, 2, 5]

輸出: 4

解釋: 有四種方式可以湊成總金額:

5=55=2+2+1

5=2+1+1+1

5=1+1+1+1+1

示例 2:

輸入: amount = 3, coins = [2]

輸出: 0

解釋: 只用面額2的硬幣不能湊成總金額3。

示例 3:

輸入: amount = 10, coins = [10] 

輸出: 1

注意:

你可以假設:

0 <= amount (總金額) <= 5000

1 <= coin (硬幣面額) <= 5000

硬幣種類不超過 500 種

結果符合 32 位符號整數

要得到總的組合數,狀態轉移方程為:

d p[

i][j

]=dp

[i−1

][j]

+dp[

i][j

−coi

n]

dp[i][j] = dp[i - 1][j] + dp[i][j-coin]

dp[i][

j]=d

p[i−

1][j

]+dp

[i][

j−co

in]

**:

class

solution

}return dp[n]

[amount];}

}

狀態壓縮:通過觀察可以發現,dp陣列的轉移只和dp[i][..]dp[i-1][..]有關,所以可以壓縮狀態,進一步降低演算法的空間複雜度。

class

solution

}return dp[amount];}

}

下面兩題為完全揹包的變體:物品可以無限次選取,且考慮物品放入揹包的順序

377,組合總和ⅳ,medium

給定乙個由正整數組成且不存在重複數字的陣列,找出和為給定目標正整數的組合的個數。

示例:

nums = [1, 2, 3]

target = 4

所有可能的組合為:

(1, 1, 1, 1)

(1, 1, 2)

(1, 2, 1)

(1, 3)

(2, 1, 1)

(2, 2)

(3, 1)

請注意,順序不同的序列被視作不同的組合。

因此輸出為 7。

139,單詞拆分,medium

給定乙個非空字串 s 和乙個包含非空單詞的列表 worddict,判定 s 是否可以被空格拆分為乙個或多個在字典**現的單詞。

說明:拆分時可以重複使用字典中的單詞。

你可以假設字典中沒有重複的單詞。

示例 1:

輸入: s = "leetcode", worddict = ["leet", "code"]

輸出: true

解釋: 返回 true 因為 "leetcode" 可以被拆分成 "leet code"。

示例 2:

輸出: true

注意你可以重複使用字典中的單詞。

示例 3:

輸入: s = "catsandog", worddict = ["cats", "dog", "sand", "and", "cat"]

輸出: false

完全揹包問題總結

做題步驟

理解題意,判定此題為 完全揹包問題 或 完全揹包問題的變體。根據所求分為組合問題,true/false問題,最大最小問題。通常用一維 dpdp

dp陣列解題。

此題是否有特殊情況

動態規劃正常做法

1. 子問題:確定揹包和物品指代什麼,$dp[i]$ 返回值是什麼

2. base case:通常為 $dp[0]$

3. 狀態轉移方程:

**先遍歷揹包,再遍歷物品。**這樣才能保證放入順序。

組合問題公式 dp[i] += dp[i - num]

true/false問題公式 dp[i] = dp[i] or dp[i - num]

最大最小問題公式 dp[i] = min(dp[i], dp[i - num]+1) 或 dp[i] = max(dp[i], dp[i - num]+1)

最終返回結果

leetcode演算法刷題 五 動態規劃 三

今天的題目不是leetcode上面的。只是覺得動態規劃還是不算很熟練,就接著找了點dp的題練練 題目的意思 傳入乙個陣列,要求出它的最長遞增子串行的長度。例如 如在序列1,1,2,3,4,5,6,7中,最長遞增序列為1,2,4,6,所以長度為4。分析 這道題我們可以用動態規劃來做。對於陣列的前i個元...

leetcode刷題 動態規劃

動態規劃 英語 dynamic programming,簡稱 dp 是一種在數學 管理科學 電腦科學 經濟學和生物資訊學中使用的,通過把原問題分解為相對簡單的子問題的方式求解複雜問題的方法。動態規劃常常適用於有重疊子問題和最優子結構性質的問題,動態規劃方法所耗時間往往遠少於樸素解法。動態規劃背後的基...

Leetcode刷題 190713 動態規劃

輸入乙個陣列,陣列中每個元素代表乙個房子,我們作為robber可以對每個房子進行rob。但是規定不能同時又兩個相鄰的房子被robbed。陣列中每個元素的值代表房子的價值,需要我們輸出經過rob後最大的收益是多少。很明顯考察的是動態規劃,每檢查乙個房子都有兩種狀態即rob和no rob。對應的價值方程...