2020.7.23 力扣每日

 1 class Solution {
 2     public int minPathSum(int[][] grid) {
 3         int row = grid.length;
 4         int col = grid[0].length;
 5         int[][] dp = new int[row][col];
 6         if (row == 0 || col == 0)                                  //空数组
 7             return 0;
 8         dp[0][0] = grid[0][0];
 9         for (int i = 1; i < row; i++){                             //设置第1列
10             dp[i][0] = dp[i - 1][0] + grid[i][0];                 
11         }
12         for (int i = 1; i < col; i++){                             //设置第1行
13             dp[0][i] = dp[0][i - 1] + grid[0][i];
14         }
15         for (int i = 1; i < row; i++){                             //遍历其余位置
16             for (int j = 1; j < col; j++){
17                 int up = dp[i - 1][j] + grid[i][j];                //从上移动到当前节点
18                 int left = dp[i][j - 1] + grid[i][j];              //从左移动到当前节点
19                 dp[i][j] = (up < left) ? up : left;                //比较去最小值
20             }
21         }
22         return dp[row - 1][col - 1];
23     }
24 }

解题思路:

   这是一道经典的动态规划题目,由于移动方向为向右与向下,说明除了第一行第一列以外,其余点的对应最小路径和,只可能是从左移动至当前位置的路径和,或是从上方移动至当前位置的路径和。我们使用二维数组dp[row][col]存储所有点的对应路径和情况。

   用up,left分别存储从上,与从左的两种情况,显然动态方程为dp[i][j] = (up < left) ? up : left;

注意点:

  • 对于第一列,由于其没有左方元素,所以dp值为dp[i - 1][0] + grid[i][0]
  • 对于第一行,由于其没有上方元素,所以dp值为dp[0][i - 1] + grid[0][i]

空间复杂度:O(M*N),M,N为矩阵的行数与列数

时间复杂度:O(M*N)

优化:

   我们发现,事实上每一行的元素的dp值,实际上只使用到了上一行的dp值与该行的前一位dp值,所以可以通过设置一维数组dp[col],优化空间复杂度。

 1 class Solution {
 2     public int minPathSum(int[][] grid) {
 3         int row = grid.length;                    
 4         int col = grid[0].length;
 5         int[] dp = new int[col];
 6         if (col == 0)                                            //数组为空
 7             return 0;
 8         dp[0] = grid[0][0];                                   
9
for (int i = 1; i < col; i++){ //设置第一行的dp 10 dp[i] = dp[i - 1] + grid[0][i]; 11 } 12 for (int i = 1; i < row; i++){ //遍历其余行 13 dp[0] = dp[0] + grid[i][0]; //每行开始为上一行+当前值 14 for (int j = 1; j < col; j++){ 15 int left = dp[j - 1] + grid[i][j]; //从左处移动到当前节点 16 int up = dp[j] + grid[i][j]; //从上方移动到当前节点上 17 dp[j] = (left < up) ? left : up; //取最小值 18 } 19 } 20 return dp[col - 1]; 21 } 22 }

解题思路:

扫描二维码关注公众号,回复: 11425730 查看本文章

   同样,先设置第一行的dp值。在通过循环遍历,对于每个节点来说,还未计算时,对应的dp[j]存储的是上方节点的情况,而dp[j -1]则对应的是左方节点的情况,所以我们只需改变先前算法,使left = dp[j -1] + grid[i][j], up = dp[j] + grid[i][j]。最后修改dp[j]为两者中的最小值即可。

注意点:

   同样,第一行与第一列需特殊处理。

  • 第一行,为dp[i - 1] + grid[0][i]
  • 第一列,为dp[i] + grid[i][0]

空间复杂度:O(N),N为矩阵的列数

时间复杂度:O(M*N)

题后总结:

   优:对于经典的动态规划熟练掌握,能迅速的解出,并进行一定的优化

   差:代码部分仍可精简,如使用Math.min

猜你喜欢

转载自www.cnblogs.com/-TTY/p/13369227.html