题目描述:具体描述见原题,简单来说就是求最小路径和。
解题思路:考虑dp,最常规解法是构造二维数组,初始化边界值,非边界值状态转移方程是dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j]。稍微优化一下将辅助空间变为一维数组,左边界状态转移方程是dp[j] += triangle[i][0],右边界为dp[j] = dp[j-1] + triangle[i][j],非边界值状态转移方程是dp[j] = min(dp[j-1]+triangle[i][j], dp[j]+triangle[i][j])。在优化一下无需辅助空间,采用倒叙dp。状态转移方程为triangle[row][col] += min(triangle[row+1][col], triangle[row+1][col+1])。具体过程见代码。
具体代码:
// 辅助空间为二维数组
func minimumTotal(triangle [][]int) int {
if len(triangle) == 0 || len(triangle[0]) == 0 {
return 0
}
m := len(triangle)
dp, res := make([][]int, m), math.MaxInt32
for i := 0; i < m; i++ {
dp[i] = make([]int, i+1)
}
dp[0][0] = triangle[0][0]
for i := 1; i < m; i++ {
dp[i][0] = dp[i-1][0] + triangle[i][0]
}
res = min(res, dp[m-1][0])
for i := 1; i < m; i++ {
dp[i][i] = dp[i-1][i-1] + triangle[i][i]
}
res = min(res, dp[m-1][m-1])
for i := 1 ; i < m; i++ {
for j := 1; j < len(dp[i]) -1; j++ {
dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j]
if i == m - 1 {
res = min(res, dp[i][j])
}
}
}
return res
}
// 辅助空间为一维数组
func minimumTotal(triangle [][]int) int {
if len(triangle) == 0 {
return 0
}
dp, res := make([]int, len(triangle[len(triangle)-1])), math.MaxInt64
for i := 0; i < len(triangle[0]); i++ {
dp[i] = triangle[0][i]
}
for i := 1; i < len(triangle); i++ {
for j := len(triangle[i]) - 1; j >= 0; j-- {
if j == 0 {
dp[j] += triangle[i][0]
} else if j == len(triangle[i])-1 {
dp[j] = dp[j-1] + triangle[i][j]
} else {
dp[j] = min(dp[j-1]+triangle[i][j], dp[j]+triangle[i][j])
}
}
}
for i := 0; i < len(dp); i++ {
res = min(dp[i], res)
}
return res
}
// 无需辅助空间
func minimumTotal(triangle [][]int) int {
if len(triangle) == 0 {
return 0
}
for row := len(triangle) - 2; row >= 0; row-- {
for col := 0; col < len(triangle[row]); col++ {
triangle[row][col] += min(triangle[row+1][col], triangle[row+1][col+1])
}
}
return triangle[0][0]
}
补充说明:这道题是简单dp,倒叙dp的方法不知道是谁想出来的,有点东西。又开始分开办公了。