1. 程式人生 > >LeetCode 64最小路徑和

LeetCode 64最小路徑和

題目

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

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

示例:

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

解釋

此題運用的是動態規劃, 而且和很多題目非常相似,題目要求每次只能向下走一步或者向右走一步。這就規定走到這一個點的路徑只有兩點,就是上面的點和左邊的點。所以每一點的最小cost可以表示為

min(到達上面的點的最小cost, 到達左邊的點的最小cost) + 當前點的 cost

這樣就把問題分成子問題,建立一個二維陣列cost用來儲存到達每一點的最小cost。

遞迴式可以表示為

  cost[i][j] = min(cost[i][j - 1] + grid[i][j], cost[i - 1][j] + grid[i][j]);

然後利用一個二層迴圈,把到達每一個點的最小值求出來。返回返回右下角的值即可。

程式碼

    int minPathSum(vector<vector<int>>& grid) {
        vector<vector<int>> cost = grid;
        int n = grid.size(), m = grid[0].size();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
	            //處理第一行和第一列的情況,如果不處理的話,陣列會越界
                if (i == 0) {
	                //一直向右走
                    cost[i][j] = cost[i][j - 1] + grid[i][j];
                } else if (j == 0) {
	                //一直向下走
                    cost[i][j] = cost[i - 1][j] + grid[i][j];
                } else {
	                //利用遞推式求結果
                    cost[i][j] = min(cost[i][j - 1] + grid[i][j], cost[i - 1][j] + grid[i][j]);
                }
            }
        }
        //返回右下角值
        return cost[n-1][m-1];
    }

總結

  • 關鍵的一點就是找出遞推式。看當前最優解能否被前面的值推出
  • 儲存原來的資料一般可以用一個二維陣列。但是有一些題目對空間有限制。比如LeetCode 413, 這樣的話就要儘量去優化,看能不能用一維陣列來代替。

類似題目