64. 最小路径和 中等

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例 1:

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。

示例 2:

输入:grid = [[1,2,3],[4,5,6]]
输出:12

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • 0 <= grid[i][j] <= 100

代码参考:

package main

import (
    "fmt"
)

func main() {
    fmt.Println(minPathSum([][]int{
        {1, 3, 1},
        {1, 5, 1},
        {4, 2, 1},
    }))
}

// 考虑使用递归实现,到达 grid[i][j] 的最小路径为到达 grid[i-1][j] 和 grid[i][j-1] 的最小值
// 但递归不保存任何已计算出的结果,效率不高,类比斐波那契数列的递归实现
// 使用简单的动态规划,即保存中间计算结果
func minPathSum(grid [][]int) int {
    if len(grid) <= 0 || len(grid[0]) <= 0 {
        return 0
    }

    row, column := len(grid), len(grid[0])
    steps := make([][]int, row) // 存储到达 [i,j] 的最少步数
    for i := range steps {
        steps[i] = make([]int, column)
    }
    steps[0][0] = grid[0][0]

    // 只能向下或向左移动,先求解简单值
    // 首行
    for c := 1; c < column; c++ {
        steps[0][c] = grid[0][c] + steps[0][c-1]
    }
    // 首列
    for r := 1; r < row; r++ {
        steps[r][0] = grid[r][0] + steps[r-1][0]
    }

    // 再根据简单值,逐步求解复杂值
    // 从 [1][1] 开始走到右下顶点
    for r := 1; r < row; r++ {
        for c := 1; c < column; c++ {
            // 从上方,左方选最小的权值
            steps[r][c] = min(steps[r-1][c], steps[r][c-1]) + grid[r][c]
        }
    }

    return steps[row-1][column-1] // 累加到右下角的值是最小权值
}

func min(x, y int) int {
    if x > y {
        return y
    }
    return x
}
最后编辑: kuteng  文档更新时间: 2021-06-05 10:16   作者:kuteng