[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,相对就比较好做了。

面试应该说出思路就好了,代码还是太繁琐了。。。

posted @ 2018-10-02 17:37  Lin.B  阅读(101)  评论(0编辑  收藏  举报