題源:IOI飛入尋常百姓家
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
n = len(triangle)
dp = [[0] * (i + 1) for i in range(n)]
dp[0][0] = triangle[0][0]
for i in range(1, n):
dp[i][0] = dp[i - 1][0] + triangle[i][0]
dp[i][i] = dp[i - 1][i - 1] + triangle[i][i]
for j in range(1, i):
dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j]
return min(dp[n - 1])
狀態轉移方程dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j]
,非常的直觀,但是需要主要邊界條件需要注意,即dp[i][0]和dp[i][i]
的取值是固定的,需要在進行每一層的dp之前/後額外寫程式碼完成初始化,以免出現邊界條件問題
最佳化成空間複雜度O(N)
的方法:
只需要維護兩行的狀態,而不是整個三角形的狀態。我們可以使用兩個一維陣列,分別表示當前行和上一行的狀態
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
n = len(triangle)
dp = [0] * n
dp[0] = triangle[0][0]
for i in range(1, n):
dp[i] = dp[i - 1] + triangle[i][i] # 更新最右側元素
for j in range(i - 1, 0, -1):
dp[j] = min(dp[j - 1], dp[j]) + triangle[i][j]
dp[0] = dp[0] + triangle[i][0] # 更新最左側元素
return min(dp)