DP 03 動態規劃演算法題目解析

2022-06-17 15:00:10 字數 3714 閱讀 8724

面試題14- i. 剪繩子/343. 整數拆分

面試題42. 連續子陣列的最大和/53. 最大子序和

面試題47. 禮物的最大價值

給定乙個正整數 n,將其拆分為至少兩個正整數的和,並使這些整數的乘積最大化。 返回你可以獲得的最大乘積。

示例 1:

輸入: 2

輸出: 1

解釋: 2 = 1 + 1, 1 × 1 = 1。

示例 2:

輸入: 10

輸出: 36

解釋: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

假設n的最大值為f(n),可以將n拆分成i和n-i,問題變成 i乘以f(n-i),這樣就變成了f(k),k

和第一步一樣,使用dp表示其值,但是要注意 i * (n - i) 本省也可能成為最大值;另外因為是遍歷迴圈,要考慮計算過的dp[i],因此得到如下表示式:

dp[i] = max(dp[i], max(i * dp(n - i),i * (n - i)))

初始值:每個dp都設定為1

而這裡的 n 是什麼呢?我們說了dp是自底向下的思考方式。因此這裡的 n 實際上是 1,2,3,4... n。

自然地,我們用一層迴圈來生成上面一系列的 n 值。接著我們還要生成一系列的 i 值,注意到 n - i 是要大於 0 的,因此 i 只需要迴圈到 n - 1 即可。

因為要迴圈使用,所以無法進行空間優化

classsolution:

defintegerbreak(self, n: int) -> int:

dp=[1]*(n+1)

fori inrange(3,n+1):

forj inrange(1,i):

dp[i] = max(j*dp[i-j],j*(i-j),dp[i])

returndp[-1]

輸入乙個整型陣列,陣列裡有正數也有負數。陣列中的乙個或連續多個整數組成乙個子陣列。求所有子陣列的和的最大值。

要求時間複雜度為o(n)。

示例1:

輸入: nums = [-2,1,-3,4,-1,2,1,-5,4]

輸出: 6

解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。

問題比較簡單,一維陣列的問題。

假設n的最大值為f(n),可以將n拆分成i和n-i,問題變成 i加上f(n-i)或直接是f(n-i),這樣就變成了f(k),k

很明顯,使用自底向上的方式進行。具體**見2.3的**一

從**也很明顯看到,只用了

dp[i-1]

這個前置項,另外是最後輸出的

max(dp)

也需要保留,其它是暫存也沒有用到,所以可將其優化,將

dp[i-1]

用max_temp,最後的輸出使用res。具體可見**二。

**一:

classsolution:

defmaxsubarray(self, nums: list[int]) -> int:

n = len(nums)

ifn == 0:return0

else:

dp = [nums[0]] *(n)

fori inrange(1,n):

#注意這裡不是n+1

dp[i] = max(dp[i-1]+nums[i],nums[i])

returnmax(dp)

**二:

classsolution:

defmaxsubarray(self, nums: list[int]) -> int:

n = len(nums)

ifn == 0:return0

else:

max_temp = nums[0]

res = max_temp

fori inrange(1,n):

max_temp = max(max_temp + nums[i],nums[i])

res = max(res,max_temp)

returnres

在乙個 m*n 的棋盤的每一格都放有乙個禮物,每個禮物都有一定的價值(價值大於 0)。你可以從棋盤的左上角開始拿格仔裡的禮物,並每次向右或者向下移動一格、直到到達棋盤的右下角。給定乙個棋盤及其上面的禮物的價值,請計算你最多能拿到多少價值的禮物?

示例 1:

輸入:

[[1,3,1],

[1,5,1],

[4,2,1]

]輸出: 12

解釋: 路徑 1→3→5→2→1 可以拿到最多價值的禮物

是二維陣列題,難度為中等偏上,和這題【1143. 最長公共子串行】類似

題目說明:從棋盤的左上角開始拿格仔裡的禮物,並每次 向右 或者 向下 移動一格、直到到達棋盤的右下角。

根據題目說明,易得某單元格只可能從上邊單元格或左邊單元格到達。

很明顯,縮小規模的子問題和原文題是等效的。

定義二維矩陣,設動態規劃矩陣 dp,

dp(i,j)

代表從棋盤的左上角開始,到達單元格 

(i,j)

時能拿到禮物的最大累計價值。

先行後列,從上到下進行計算即可。具體**見3.3**一。

對角進行替換,換成下圖所示的例子,進一步優化空間:

temp

dp[j-1]

dp[j-1]

只是用上面和左邊的,所以可以重複利用,迴圈推進就可以了。具體見**二。

**一:

classsolution:

defmaxvalue(self, grid: list[list[int]]) -> int:

m = len(grid)

n = len(grid[0])

dp = [[0]*(n+1) for_ inrange(m+1)]   #(m+1)(n+1)

的矩陣fori inrange(1,m+1):   #

注意要從

1開始,結束為

m+1forj inrange(1,n+1):

dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + grid[i-1][j-1]

returndp[-1][-1]

classsolution:

defmaxvalue(self, grid: list[list[int]]) -> int:

m = len(grid)

n = len(grid[0])

dp = [0]*(n+1)    #(n+1)

的陣列fori inrange(1,m+1):   #

注意要從

1開始,結束為

m+1forj inrange(1,n+1):

temp = dp[j]

#這個也可省略,因為是迴圈更新,可以代表d[i-1][j]

dp[j] = max(temp,dp[j-1]) + grid[i-1][j-1]

returndp[-1]

動態規劃演算法(DP)

動態規劃演算法採用分治演算法的思想,將原問題分成若干個子問題,然後分別求解各個子問題,最後將子問題的解組合起來得到原問題的解。分治演算法遞迴地求解各個子問題,可能重複求解某些子問題。與分治演算法不同的是,動態規劃演算法不是遞迴地求解各個子問題,它是從簡單問題的解入手,逐步求解,直至求解出原問題。動態...

動態規劃演算法解析

數字三角形 poj1163 在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或 右下走。只需要求出這個最大和即可,不必給出具體路徑。三角形的行數大於1小於等於100,數字為 0 99 輸入格式 5 表示三角形的行數 接下來輸入三角形 3 88...

動態規劃演算法

一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...