题目
分析过程
1.自上而下
还是用到动态规划的思想
1.用 dp(i,j) 表示从三角形顶端,走到坐标 (i,j) 的所有路径中最小的路径和
2.根据题意,坐标 (i,j)只可能由它左上角或右上角走过来,因此这两个点的坐标分别为dp(i-1,j-1),dp(i-1,j)
3.给出dp(i,j) 的状态转移方程,我们只需要对左上角坐标和右上角坐标的最短路径和求较小值,然后再加上坐标 (i,j) 的元素值就可以得到 dp(i,j), 即
dp(i,j) = min(dp(i-1,j-1),dp(i-1,j)) + a(i,j)
考虑以下特殊情况
1.三角形的顶点,状态值 dp(0,0) 就等于它的元素值 a(0,0),
2.三角形的两条边,三角形左边上的每个点都只能由上一行第1个位置走来,因此 dp(i,0) 就等于上一行的 d(i-1,0) 加上当前元素值 a(i,0);而三角形右边上的每个点,都只能由上一行最后一个位置走来,因此状态 dp(i,i) 等于 dp(i-1,i-1) 加上当前元素值 a(i,i)。.
代码
func minimumTotal(triangle [][]int) int {
n := len(triangle) // 取出三角形行数
dp := make([][]int, n) // 定义状态数组dp
for i := range dp {
dp[i] = make([]int, n)
}
dp[0][0] = triangle[0][0] //初始化
for i := 1; i < n; i++ {
dp[i][0] = dp[i-1][0] + triangle[i][0] // 第i行首尾两个位置的状态值
dp[i][i] = dp[pi-1][i-1] + triangle[i][i] //一般情况
for j := 1; j < i; j++ {
dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j]
}
}
res := dp[n-1][0]
for i := 1; i < n; i++ { // i 从1遍历到n-1
res = min(min, dp[n-1][i]) // 计算最后一行状态的最小值
}
return res
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
2.自下而上
思路基本相同
func minimumTotal(triangle [][]int) int {
for i:=len(triangle)-2;i>=0;i--{ //i从n-2开始遍历到0
for j:=0;j<len(triangle[i]);j++{
triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1])
}
}
return triangle[0][0] //循环结束后返回(0,0)
}
func min(a,b int) int{
if a<b{
return a
}
return b
}