Leetcode 64:最小路径和(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/82805129

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

**说明:**每次只能向下或者向右移动一步。

示例:

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

解题思路

实际上这个问题和之前的问题Leetcode 200:岛屿的个数(最详细的解法!!!)Leetcode 79:单词搜索(最详细的解法!!!) 很类似。

这个问题通过递归很好解决,对于上面的例子来说。我们要知道1开始的最小路径,那么我们只要知道周围13的最小路径即可,以此类推下去即可。我们这里的边界条件就是我们递归到底的时候,也就是

self.r, self.c = len(grid), len(grid[0])
row == self.r - 1 and col == self.c - 1

并且我们还要考虑右上角和左下角的情况,所以我们写出这样的代码。

class Solution:
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not grid:
            return 0

        self.r, self.c = len(grid), len(grid[0])
        return self._minPathSum(0, 0, grid)

    def _minPathSum(self, row, col, grid):
        if row == self.r - 1 and col == self.c - 1:
            return grid[row][col]

        if row + 1 < self.r and col + 1 < self.c:
            return grid[row][col] + min(self._minPathSum(row, col + 1, grid), self._minPathSum(row + 1, col, grid))

        if row + 1 < self.r:
            return grid[row][col] + self._minPathSum(row + 1, col, grid)
        
        if col + 1 < self.c:
            return grid[row][col] + self._minPathSum(row, col + 1, grid)

但是这样做存在着大量的重复运算(在哪呢?)。我们可以通过记忆化搜索的方式来优化上面的问题。

class Solution:
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not grid:
            return 0

        self.r, self.c = len(grid), len(grid[0])
        mem = [[0 for i in range(self.c)] for j in range(self.r)]
        return self._minPathSum(0, 0, grid, mem)

    def _minPathSum(self, row, col, grid, mem):
        if row == self.r - 1 and col == self.c - 1:
            return grid[row][col]

        if mem[row][col]:
            return mem[row][col]

        if row + 1 < self.r and col + 1 < self.c:
            mem[row][col] = grid[row][col] + min(self._minPathSum(row, col + 1, grid, mem),\
                                            self._minPathSum(row + 1, col, grid, mem))
            return mem[row][col]

        if row + 1 < self.r:
            mem[row][col] = grid[row][col] + self._minPathSum(row + 1, col, grid, mem)
            return mem[row][col]
        
        if col + 1 < self.c:
            mem[row][col] = grid[row][col] + self._minPathSum(row, col + 1, grid, mem)
            return mem[row][col]s

实际上我们这里通过迭代的方式去写这个问题更加简洁。无非就是,先将第一行和第一列元素分别向后累加。

[
  [1,4,5],
  [2,5,1],
  [6,2,1]
]

然后考虑,第二行和第二列以及之后的元素问题,例如上面列中的中间元素,我们要考虑左边加过来和上面加下来,那个值更小min(4+5,2+5),同理以此类推。

class Solution:
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not grid:
            return 0

        r, c = len(grid), len(grid[0])
        mem = [[0 for i in range(c)] for j in range(r)]
        mem[0][0] = grid[0][0]
        for i in range(1, c):
            mem[0][i] = grid[0][i] + mem[0][i - 1]

        for i in range(1, r):
            mem[i][0] = grid[i][0] + mem[i - 1][0]

        for i in range(1, r):
            for j in range(1, c):
                mem[i][j] = grid[i][j] + min(mem[i - 1][j], mem[i][j - 1])

        return mem[r - 1][c - 1]

当然对于这个我问题,我们也可以如之前问题Leetcode 120:三角形最小路径和(最详细的解法!!!) 一样反过来思考。

class Solution:
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not grid:
            return 0

        self.r, self.c = len(grid), len(grid[0])
        mem = [[0 for i in range(self.c)] for j in range(self.r)]
        return self._minPathSum(grid,0, 0, mem)

    def _minPathSum(self, grid, row, col, mem):
        if row == self.r - 1 and col == self.c - 1:
            mem[row][col] = grid[row][col]
            return mem[row][col]

        if row == self.r - 1:
            mem[row][col] = grid[row][col] + self._minPathSum(grid, row, col + 1, mem)
            return mem[row][col]

        if col == self.c - 1:
            mem[row][col] = grid[row][col] + self._minPathSum(grid, row + 1, col, mem)
            return mem[row][col]

        if not mem[row][col]:
            mem[row][col] = grid[row][col] + min(self._minPathSum(grid, row, col + 1, mem), 
                                                    self._minPathSum(grid, row + 1, col, mem))
        return mem[row][col] 

这个问题也可以使用最短路径算法解决,但是有点大材小用了。

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/82805129
今日推荐