LeetCode 64. 最小路径和:

150 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

64. 最小路径和

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

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

示例:

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

链接:leetcode-cn.com/problems/mi…

思路: 参考 LeetCode题解(没有题解自己做,写成了回溯法,遍历所有可能 = =,答案还是错的 哎~)

搜索的做法仅仅在数据规模比较小的时候才考虑使用,因为复杂度较高,所以采用dp。由于每个元素对应的最小路径和与其相邻元素(当前点的面或面)对应的最小路径和有关,因此可以使用动态规划求解。

动态规划:从左上角(0, 0)移动到右下角,每次选择最小的节点值移动:

(1) 位于原点(0,0)时,不做任何处理

(2) 当前点位于最上面一行(上边界x=0)时:只能从原点向右移动,从"左"边过来

(3) 当前点位于最左边一列(左边界y=0)时:只能从原点向下移动,从"上"边过来

(4) 当前点既不在最上面一行(i != 0),也不在最左边一列(j != 0),此时选取其或其位置点的最小值

时间复杂度: O(m * n)   遍历整个 gridgrid 矩阵元素

空间复杂度: O(1)          直接修改原矩阵,不使用额外空间

// dp:
int minPathSum(vector<vector<int>>& grid) {
    for (int i = 0; i < grid.size(); i++)
    {
        for (int j = 0; j < grid[0].size(); j++)
        {
            if (i == 0 && j == 0) // (1) 位于原点(0,0)时
            {
                continue;
            }
            else if (i == 0)      // (2) 当前点位于最上面一行(上边界x=0)时:只能从原点向右移动,从"左"边过来
            {
                grid[i][j] = grid[i][j - 1] + grid[i][j]; 
            }
            else if (j == 0)      // (3) 当前点位于最左边一列(左边界y=0)时:只能从原点向下移动,从"上"边过来
            {
                grid[i][j] = grid[i - 1][j] + grid[i][j];
            }
            else                  // (4) 当前点既不在最上面一行(i != 0),也不在最左边一列(j != 0),此时选取其上或其左位置点的最小值
            {
                grid[i][j] = min(grid[i - 1][j]/*上面位置*/, grid[i][j - 1]/*左面位置*/) + grid[i][j];
            }
        }
    }
    return grid[grid.size() - 1][grid[0].size() - 1];    // 最终返回右下角的累计的最小路径和
}