[leetcode] Minimum Path Sum
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Example:
Input: [ [1,3,1], [1,5,1], [4,2,1] ] Output: 7 Explanation: Because the path 1→3→1→1→1 minimizes the sum.
分析:题目意思也很简单,从左上角到右下角,只能往右和下走,要求从找一条路使得路径上和最小。
很明显使用动态规划来求解,下面就来做动态规划三要素:
1、dp[i][j]代表走到[i][j]位置路径和最小的和
2、边界条件初始化:
dp[0][0] = grid[0][0]
dp[0][j] = dp[0][j-1] + grid[0][j]
dp[i][0] = dp[i-1][0] + grid[i][0]
3、状态转移方程:可以这么考虑,因为只能向右向下,因此到第[i][j]位置只能有两条路,只要找到这两个路最小的那个就可以了。
dp[i][j] = min(dp[i][j-1],dp[i-1][j]) + grid[i][j]
所以代码如下:
1 class Solution { 2 public int minPathSum(int[][] grid) { 3 int M = grid.length; 4 int N = grid[0].length; 5 int[][] dp = new int[M][N]; 6 7 dp[0][0] = grid[0][0]; 8 for ( int j = 1 ; j < N ; j ++ ) dp[0][j] = dp[0][j-1] + grid[0][j]; 9 for ( int i = 1 ; i < M ; i ++ ) dp[i][0] = dp[i-1][0] + grid[i][0]; 10 11 for ( int i = 1 ; i < M ; i ++ ){ 12 for ( int j = 1 ; j < N ; j ++ ){ 13 dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1]) + grid[i][j]; 14 } 15 } 16 return dp[M-1][N-1]; 17 18 } 19 }
运行时间6ms。
这个题目还是比较简单的,之前面试滴滴也遇到过。上次面试接着又问了一个有深度的问题:现在问题变成从左上角到右下角再回到左上角,要求找这个闭环的路径和最小值,要求不能有重复。
比如上面的例题,最后应该是找到1→3→1→1→1→2→4→1→1。
正确的思路:正确的理解,相当于从左上角到右下角,找两个路径,这两个路径和是最小和次小。因此使用四维dp,(i,j)(p,q),每一个状态转移的时候都有四个参数要更新。(i,j)用来记录最小的路径,(p,q)用来记录次小的路径,这里要注意找次小的时候要去掉最小的路径。
四维dp是非常麻烦的,下面如何简化,也就是降维呢?这里注意到(i,j)(p,q)的关系:i+j==p+q。有了这个关系,就可以把四维dp降到三维dp,相对就比较好做了。
面试应该说出思路就好了,代码还是太繁琐了。。。