"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid

I have prepared 1,000 e-books and 100 high-definition mind maps in various fields of computer, and I will reply to [Resources] after paying attention to get it! You can even reply [introduction] to join the BAT introduction group!

"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid

In the previous article, through analysis, we successfully completed the dynamic programming problem of "triangular minimum path sum". In this section, we continue to look at a similar question type in order to fully grasp this "path sum" problem. Not much to say, first look at the topic:

01, topic analysis


Question 64: Minimum path sum


Given an mxn grid containing non-negative integers, please find a path from the upper left corner to the lower right corner so that the sum of the numbers on the path is the smallest.


Note: You can only move one step down or right at a time.

Example:

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

This question has a certain degree of difficulty! If you have no ideas, please review the learning content of the previous article!

It is not recommended to look at the solution directly!

02, topic illustration


First, we analyze the topic, looking for a minimum path and , What is that mean? Suppose we have a m * n rectangle: [[1,3,1],[1,5,1],[4,2,1]]
"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid

Then the minimum path sum from the upper left corner to the lower right corner , we can easily see that it is 1-3-1-1-1, this path, the result is equal to 7.

The topic is clear, we continue to analyze. This question is the same as the previous one to find the minimum path sum of the triangle. The question obviously conforms to that it can be constructed from the optimal solution of the sub-problem , so we consider using dynamic programming to solve it. First, we define the state:

dp[i][j] : 表示包含第i行j列元素的最小路径和

Similarly, because any path to the lower right corner will pass through the element [0,0]. So we need to initialize dp[0][0].


dp[0][0] = [0][0]位置所在的元素值

Continuing the analysis, according to the conditions given by the title, if we require dp[i][j], then it must have moved from above or to the left. As shown below:

"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid

5, can only move from 3 or 1
2, can only move from 5 or 4,
4, move from 1
3, move from 1
(the red position must move from the blue position)
and then we Get the state transition equation:

dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]
Also we need to consider two special cases:

  • The top row can only be moved from the left (1-3-1)
  • The leftmost column can only be moved from above (1-1-4).
    "Sword Finger Offer" Day 29: The minimum path sum of the mxn grid
    Finally, because our goal is to walk from the upper left corner to the lower right corner, the minimum path sum of the entire grid is actually the minimum path sum containing the elements in the lower right corner . which is:

Suppose: the length of dp is l and the
final result is: dp[l-1][len(dp[l-1])-1] In
summary, we have finished the analysis, and we have performed a total of 4 steps:

1. Define the state
2. Summarize the state transition equation
3. Analyze the special cases that the state transition equation cannot satisfy.
4. Get the final solution

03, GO language example


According to the above analysis, the code can be obtained as follows:

![](https://s4.51cto.com/images/blog/202101/27/5486729781abbd79236bd4939d76a6ac.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)func minPathSum(grid [][]int) int {
 l := len(grid)
 if l < 1 {
  return 0
 }
 dp := make([][]int, l)
 for i, arr := range grid {
  dp[i] = make([]int, len(arr))
 }
 dp[0][0] = grid[0][0]
 for i := 0; i < l; i++ {
  for j := 0; j < len(grid[i]); j++ {
   if i == 0 && j != 0 {
    dp[i][j] = dp[i][j-1] + grid[i][j]
   } else if j == 0 && i != 0 {
    dp[i][j] = dp[i-1][j] + grid[i][j]
   } else if i !=0 && j != 0 {
    dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
   }
  }
 }
 return dp[l-1][len(dp[l-1])-1]
}

func min(a, b int) int {
 if a > b {
  return b
 }
 return a
}

operation result:
"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid

Similarly, running the above code, we find that the memory used is too large. Is there any way to compress memory? Through observation, we found that in the process of calculating the minimum path sum of each node from the upper left corner to the lower right corner, we only need to use the data that has been accumulated before, and will not access the previous element data again . The drawing is as follows: (Everyone sees that this process looks like minesweeping. In fact, if you study the minesweeping plug-in, you will find that there is an analysis method that is quite similar to this kind of analysis method in the core algorithm of minesweeping. I will not go into it here.)

"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid
The optimized code is as follows:


func minPathSum(grid [][]int) int {
 l := len(grid)
 if l < 1 {
  return 0
 }
 for i := 0; i < l; i++ {
  for j := 0; j < len(grid[i]); j++ {
   if i == 0 && j != 0 {
    grid[i][j] = grid[i][j-1] + grid[i][j]
   } else if j == 0 && i != 0 {
    grid[i][j] = grid[i-1][j] + grid[i][j]
   } else if i !=0 && j != 0 {
    grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
   }
  }
 }
 return grid[l-1][len(grid[l-1])-1]
}

func min(a, b int) int {
 if a > b {
  return b
 }
 return a
}

operation result:

"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid
java:

class Solution {
    public int minPathSum(int[][] grid) {
        int l = grid.length;
        if (l < 1) {
            return 0;
        }
        for(int i = 0; i < l; i++)  {
            for(int j = 0; j < grid[i].length; j++)  {
                if (i == 0 && j != 0) {
                    grid[i][j] = grid[i][j-1] + grid[i][j];
                } else if (j == 0 && i != 0) {
                    grid[i][j] = grid[i-1][j] + grid[i][j];
                } else if (i !=0) {
                    grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j];
                }
            }
        }
        return grid[l-1][grid[l-1].length - 1];
    }

    public int min(int a, int b) {
        return a > b ? b : a;
    }

}

operation result:
"Sword Finger Offer" Day 29: The minimum path sum of the mxn grid

Thoughts after class: What is the difference between the path and class problem and the previous sub-sequence problem?

Guess you like

Origin blog.51cto.com/15076236/2608566