LeetCode 热题 100 64. 最小路径和
LeetCode 热题 100 | 64. 最小路径和
大家好,今天我们来解决一道经典的动态规划问题——最小路径和。这道题在 LeetCode 上被标记为中等难度,要求找到从网格的左上角到右下角的路径,使得路径上的数字总和为最小。
问题描述
给定一个包含非负整数的 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] <= 200
解题思路
核心思想
-
动态规划:
- 使用动态规划(DP)来解决这个问题。
- 定义
dp[i][j]
为从网格的左上角到达位置(i, j)
的最小路径和。 - 状态转移方程为:
[
dp[i][j] = \min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
]
其中,dp[i-1][j]
表示从上方到达(i, j)
的最小路径和,dp[i][j-1]
表示从左方到达(i, j)
的最小路径和。
-
初始化:
dp[0][0] = grid[0][0]
,因为从起点到起点的路径和就是起点的值。- 第一行和第一列的所有位置只能从一个方向到达,因此初始化为累加值。
-
遍历:
- 遍历整个网格,根据状态转移方程更新
dp[i][j]
。
- 遍历整个网格,根据状态转移方程更新
Python代码实现
class Solution:def minPathSum(self, grid):m, n = len(grid), len(grid[0])dp = [[0] * n for _ in range(m)]dp[0][0] = grid[0][0]# 初始化第一行for j in range(1, n):dp[0][j] = dp[0][j-1] + grid[0][j]# 初始化第一列for i in range(1, m):dp[i][0] = dp[i-1][0] + grid[i][0]# 遍历网格for i in range(1, m):for j in range(1, n):dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]return dp[m-1][n-1]
代码解析
-
初始化:
dp
数组初始化为一个m x n
的二维列表,所有值初始化为 0。dp[0][0] = grid[0][0]
,因为从起点到起点的路径和就是起点的值。- 第一行和第一列的所有位置只能从一个方向到达,因此初始化为累加值。
-
状态转移:
- 遍历从
(1, 1)
到(m-1, n-1)
的每个位置(i, j)
。 - 对于每个位置
(i, j)
,更新dp[i][j]
为min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
。
- 遍历从
-
返回结果:
- 最终结果存储在
dp[m-1][n-1]
中,表示从左上角到右下角的最小路径和。
- 最终结果存储在
复杂度分析
- 时间复杂度:O(m * n),其中
m
和n
分别是网格的行数和列数。需要遍历整个网格。 - 空间复杂度:O(m * n),使用了大小为
m x n
的dp
数组。
示例运行
示例 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
总结
通过动态规划的方法,我们可以高效地解决最小路径和问题。状态转移方程 dp[i][j] = \min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
确保了我们能够找到从左上角到右下角的最小路径和。希望这篇题解对大家有所帮助,如果有任何问题,欢迎在评论区留言讨论!
关注我,获取更多算法题解和编程技巧!