1. 程式人生 > >Leetcode 64:最小路徑和(最詳細的解法!!!)

Leetcode 64:最小路徑和(最詳細的解法!!!)

給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。

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

示例:

輸入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
輸出: 7
解釋: 因為路徑 1→3→1→1→1 的總和最小。

解題思路

這個問題通過遞迴很好解決,對於上面的例子來說。我們要知道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]*self.c for _ 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]

實際上我們這裡通過迭代的方式去寫這個問題更加簡潔。無非就是,先將第一行和第一列元素分別向後累加。

[
  [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]*self.c for _ in range(self.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]
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]*self.c for _ 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] 

這個問題也可以使用最短路徑演算法解決,但是有點大材小用了。

如有問題,希望大家指出!!!