【LeetCode】931. Minimum Falling Path Sum 解題報告(Python)
目錄
題目描述
Given a square array of integers A
, we want the minimum
sum of a falling path through A.
A falling path starts at any element in the first row, and chooses one element from each row. The next row’s choice must be in a column that is different from the previous row’s column by at most one.
Example 1:
Input: [[1,2,3],[4,5,6],[7,8,9]]
Output: 12
Explanation:
The possible falling paths are:
[1,4,7], [1,4,8], [1,5,7], [1,5,8], [1,5,9]
[2,4,7], [2,4,8], [2,5,7], [2,5,8], [2,5,9], [2,6,8], [2,6,9]
[3,5,7], [3,5,8], [3,5,9], [3,6,8], [3,6,9]
The falling path with the smallest sum is [1,4,7]
12
.
Note:
1 <= A.length == A[0].length <= 100
-100 <= A[i][j] <= 100
題目大意
從最上面一行開始向下走,每次移動的時候最多隻可以移動一列。也就是說每次必須向下走一行,列可以不變、也可以向左右移動一列。求到達最後一行的時候,最短的路徑長度。
解題方法
動態規劃
剛做過類似的題目,但是我還是沒有做出來。。這個題和799香檳塔很像,都是二維空間求最大、最小的路徑問題。
如果看上面這個圖就明白了,陣列中每個位置都要從上一層獲得三個相鄰列的最小值,換句話說,每個位置都可以給下面三個相鄰列傳遞最小值。那麼,其實就是一個動態規劃嘛,到每個位置的最短路徑,就是當前數值加上到達上面那層的三個相鄰列的最小值。
所以這個題程式碼其實很簡單,只需要設定好邊界,然後我們每次查詢上面的三個最小值加上當前的位置,得到的就是到達當前位置的最小路徑。
做DP的時候,不要怕設定邊界條件。我以前總想著用各種方法想著讓dp陣列和原來的陣列一樣大,這個思想是錯誤的!因為我們記憶化搜尋的時候實際上有很多邊界條件的,其實是可以轉化成dp的邊界條件,或者說是初始條件。提前給dp陣列設定各種邊界條件,能簡化很多狀態轉移程式碼~這個題就很好的說明了這點!
時間複雜度是O(MN),空間複雜度是O(MN)。
class Solution(object):
def minFallingPathSum(self, A):
"""
:type A: List[List[int]]
:rtype: int
"""
M, N = len(A), len(A[0])
dp = [[0] * (N + 2) for _ in range(M)]
for i in range(M):
dp[i][0] = dp[i][-1] = float('inf')
for j in range(1, N + 1):
dp[i][j] = A[i][j - 1]
for i in range(1, M):
for j in range(1, N + 1):
dp[i][j] = A[i][j - 1] + min(dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1])
return min(dp[-1])
相似題目
參考資料
日期
2018 年 10 月 28 日 —— 啊,悲傷的周賽