LeetCode-Minimum Path Sum 最短路径之和,从递归到动态规划

LeetCode-Minimum

给定一个m×n的网格,其中填充了非负数,请找到一条从左上到右下的路径,该路径为沿其路径所经过所有数字的总和的最小值。

递归实现

这题是求一个最短路径的问题,最开始我想到的是使用递归来求解。递归的终止条件为当前位置为方位的最后一个位置,返回这个位置的权重,否则返回当前权重加上向右侧/下侧方向的最小值。递归实现的方式非常简单再考虑一些边界条件即可。

class Solution {
    public int minPathSum(int[][] grid) {
        int x = grid.length;
        int y = grid[0].length;
        // 从右下向左上开始遍历,边界条件更好处理
        return findMinPath(grid, x - 1, y - 1);
    }
    
    private int findMinPath(int[][] grid, int x, int y) {
        if (x == 0 && y == 0) {
            return grid[x][y];
        }
        
        if (x == 0) {
            // 到达最上侧的边,持续左移即可
            return grid[x][y] + findMinPath(grid, x ,y - 1);
        }
        
        if (y == 0) {
            // 到达最左侧的边,持续上移
             return grid[x][y] + findMinPath(grid, x - 1 ,y);
        }
        // 分别向左侧,上侧移动
        return grid[x][y] + Math.min(findMinPath(grid, x - 1 ,y), findMinPath(grid, x, y - 1));
       
    }
}

递归的实现非常简单,但是在提交的时候抛出了Status: Time Limit Exceeded。递归解法的时间复杂度太高,执行超时了。可以简单的计算下,每个节点都有两个方向可以移动,那么一条十个节点的路径就会有 2^10 = 1024 次计算,而且大部分都是重复的计算。

动态规划

这个时候就要使用动态规划的实现方式。动态规划的思想是使用已知子问题的答案去解决未知大问题的答案。假设从起始点S(0,0) 到终点E(m,n)的最短路径经过T(x,y),则路径P是从ST的最短路径,然后剩下的问题就是从求解从TE的最短路径。我们使用一个二维数组sum来保存从起始点到当前点的最短路径之和。二维数组sum的最上一条边和最左侧的数据很容易计算得出,只需要从上到下/从左到右相加即可,然后使用已知的数据将二维数组sum的其余位置计算出来,sum[x - 1][y -1]的结果即为从起始点到终点的最短路径。

class Solution {
    public int minPathSum(int[][] grid) {
        int x = grid.length;
        int y = grid[0].length;
        int[][] sum = new int[x][y];
        sum[0][0] = grid[0][0];
        for (int i = 1; i < x; i++) {
            // 初始化最左侧数据
            sum[i][0] = sum[ i - 1][0] + grid[i][0];
        }
        
        for (int i = 1; i < y; i++) {
            // 初始化最上侧数据
            sum[0][i] = sum[0][i - 1] + grid[0][i];
        }
        
        
        for (int i = 1; i < x; i++) {
            for (int j = 1; j < y; j++) {
                // 计算其余位置数据
                sum[i][j] = Math.min(sum[i-1][j], sum[i][j - 1]) + grid[i][j];
            }
        }
        return sum[x - 1][y - 1];
    }
    
}

猜你喜欢

转载自www.cnblogs.com/K-night/p/12733504.html