【題目】
給定一個包含非負整數的 m x n
網格 grid
,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。
說明: 每次只能向下或者向右移動一步。
示例 1:
image.png
輸入: grid = [[1,3,1],[1,5,1],[4,2,1]]
輸出: 7
解釋: 因為路徑 1→3→1→1→1 的總和最小。
示例 2:
輸入: grid = [[1,2,3],[4,5,6]]
輸出: 12
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 200
【題目解析】
解題方法
這個問題可以通過動態規劃(Dynamic Programming, DP)來解決。動態規劃是一種將復雜問題分解成小問題解決的方法,通過解決子問題,逐步推導出整個問題的最優解。
對于這個問題,我們可以創建一個同樣大小的DP數組來存儲到達每個格子的最小路徑和。對于網格中的每一個格子,只能從上面或者左邊移動過來,因此到達該格子的最小路徑和就是它上面的格子和左邊格子的最小路徑和中較小的那一個加上當前格子的值。
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
# 獲取網格的行數和列數
m, n = len(grid), len(grid[0])
# 動態規劃求解
for i in range(m):
for j in range(n):
# 如果不是起點
if i != 0 or j != 0:
# 如果在網格的最左邊,則只能從上面來
if j == 0:
grid[i][j] += grid[i-1][j]
# 如果在網格的最上邊,則只能從左邊來
elif i == 0:
grid[i][j] += grid[i][j-1]
# 否則,選擇從上面來和從左邊來的較小者
else:
grid[i][j] += min(grid[i-1][j], grid[i][j-1])
# 返回到達網格右下角的最小路徑和
return grid[m-1][n-1]
執行效率
image.png
【總結】
適用問題類型
動態規劃算法特別適用于那些問題,其中最優解可以通過決策序列的方式來得到,且每個決策依賴于前一個狀態的結果。這類問題通常具有重疊子問題和最優子結構的特點,使得DP算法能夠有效減少計算重復,通過局部最優解推導出全局最優解。“最小路徑和”問題是一個典型的最優路徑問題,要求找到從網格左上角到右下角的最小總和路徑,完全符合動態規劃適用的問題類型。
解決算法:動態規劃
- 算法特點:動態規劃的核心在于解決重疊子問題并利用這些子問題的解來構建最終解。該方法通過構建一個DP表(通常是二維數組),其中DP表的每個元素代表到達該位置的最小路徑和,從而避免了重復計算,并確保了算法的高效性。
- 時間復雜度與空間復雜度:對于“最小路徑和”問題,動態規劃算法的時間復雜度為O(mn),其中m是網格的行數,n是網格的列數,因為需要遍歷整個網格來填充DP表。空間復雜度也是O(mn),因為需要一個同樣大小的DP表來存儲每個位置的最小路徑和。在一些情況下,如果能夠原地修改輸入網格或者使用滾動數組技巧,空間復雜度可以優化到O(n)或更低。
實踐意義
動態規劃不僅適用于“最小路徑和”這一特定類型的問題,它在算法設計和問題解決中占據著重要地位,能夠解決包括但不限于路徑問題、序列問題、背包問題等多種類型的問題。掌握動態規劃算法,對于提高解決復雜問題的能力、優化程序性能具有重要意義。在軟件開發和數據分析領域,動態規劃算法的應用范圍廣泛,從提升算法效率到優化資源分配等方面都發揮著關鍵作用。
綜上所述,通過應用動態規劃算法解決“最小路徑和”問題,不僅能夠有效提升問題解決的效率和質量,還能夠深化對動態規劃算法設計原理和應用場景的理解。