三角形最小路径和
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
在本题中,给定的三角形的行数为 n,并且第 i行(从 0 开始编号)包含了 i+1个数。如果将每一行的左端对齐,那么会形成一个等腰直角三角形,如下所示:
解题思路
动态规划
1、用 f[i][j]] 表示从三角形顶部走到位置 (i, j)的最小路径和。这里的位置 (i,j) 指的是三角形中第 i 行第 j 列(均从 0 开始编号)的位置。
2、由于每一步只能移动到下一行「相邻的节点」上,因此要想走到位置 (i,j),上一步就只能在位置(i−1,j−1) 或者位置 (i - 1, j)。
我们在这两个位置中选择一个路径和较小的来进行转移。
状态转移方程为:
f[i][j]=min(f[i−1][j−1],f[i−1][j])+c[i][j]
其中 c[i][j] 表示位置 (i, j) 对应的元素值。
注意第 i行有 i+1个元素,它们对应的 j 的范围为 [0,i]。
3、考虑几种特殊情况:
(1)、当 j=0 时,f[i -1][ j -1] 没有意义,此时状态转移方程需改变。
状态转移方程为:
f[i][0]=f[i−1][0]+c[i][0]
(2)、当我们在第 i行的最左侧时,我们只能从第 i−1 行的最左侧移动过来。当我们在第 i 行的最右侧时,我们只能从第 i−1 行的最右侧移动过来。
当 j=i 时,f[i−1][j] 没有意义,此时状态转移方程需改变。
状态转移方程为:
f[i][i]=f[i−1][i−1]+c[i][i]
(3)、定义边界条件
状态转移方程为:
f[0][0]=c[0][0]
4、最终的答案即为 f[n−1][0] 到 f[n−1][n−1] 中的最小值,其中 n 是三角形的行数。
代码
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
#构建三角形
n = len(triangle)
f = [[0] * n for _ in range(n)]
#定义边界
f[0][0] = triangle[0][0]
#遍历最左边的数,即当 j=0 时
for i in range(1, n):
f[i][0] = f[i - 1][0] + triangle[i][0]
#遍历中间的数,即 j<i 时
for j in range(1, i):
f[i][j] = min(f[i - 1][j - 1], f[i - 1][j]) + triangle[i][j]
#遍历最右边的数(斜线上的数),即j = i 时
f[i][i] = f[i - 1][i - 1] + triangle[i][i]
#返回最小路径值
return min(f[n - 1])
时间复杂度:O(n^2),其中 n是三角形的行数。
空间复杂度:O(n^2),我们需要一个 n∗n 的二维数组存放所有的状态。