两种方法解决最小路径和的问题,一种方法是递归(超时),另一种方法是动态规划。其实动态规划和递归原理一样,都是将大问题转化为小问题求解的方法。本题的大小问题关系是:到nums[i][j]的最小路径和等于min(到上方nums[i-1][j]的最小和,到左方nums[i][j-1]的最小和) + nums[i][j]。
一、递归方法
class Solution {
public:
/**
*
* @param matrix int整型vector<vector<>> the matrix
* @return int整型
*/
int minPathSum(vector<vector<int> >& matrix) {
// write code here
// 用动态规划的方法实现最小路径和的问题
// 原问题:求nums[0][0]到nums[i][j]的最小路径和, 该问题等于nums[i - 1][j]和nums[i][j - 1]的路径和的较小值+nums[i][j]
// 子问题就是求nums[i-1][j]和nums[i][j-1]的最小路径和
// 先尝试递归(自顶向下),再尝试动态规划(制表法,自底向上)
return dfs(matrix, matrix.size() - 1, matrix[0].size() - 1);
}
private:
// 有别的参数需要传递,所以需要重新写递归函数
int dfs (vector<vector<int>>& matrix, int i, int j) {
// i和j分别为矩阵的行坐标和列坐标
if (i == 0 && j == 0) return matrix[0][0];
// 说明nums[i][j]在第一行,则其路径只有一种:从nums[0][0]向右而来,则其路径和
else if (i == 0 && j != 0) return dfs(matrix, i, j-1) + matrix[i][j];
else if (i != 0 && j == 0) return dfs(matrix, i-1, j) + matrix[i][j];
else {
return min(dfs(matrix, i-1, j), dfs(matrix, i, j-1)) + matrix[i][j]; // 到左边元素的最小路径和右边最小路径的较小值+当前值
}
}
};二、动态规划方法
class Solution {
public:
int minPathSum(vector<vector<int>>& matrix) {
// 将递归转化为动态规划来做
// 自底向上计算最小路径,这样可以避免递归的众多重复计算
int nr = matrix.size();
if (!nr) return 0;
int nc = matrix[0].size();
vector<vector<int>> dp(nr, vector<int>(nc)); // nr * nc的数组
dp[0][0] = matrix[0][0];
// 初始化行和列
for (int i = 1; i < nr; i++) {
dp[i][0] = dp[i - 1][0] + matrix[i][0];
}
for (int i = 1; i < nc; i++) {
dp[0][i] = dp[0][i - 1] + matrix[0][i];
}
// 一行一行地填充动规数组
for (int i = 1; i < nr; i++) {
for (int j = 1; j < nc; j++) {
// 对第i行
dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + matrix[i][j];
}
}
return dp[nr - 1][nc - 1];
}
};
京公网安备 11010502036488号