1. 程式人生 > 實用技巧 >2020.7.23 力扣每日

2020.7.23 力扣每日

 1 class Solution {
 2     public int minPathSum(int[][] grid) {
 3         int row = grid.length;
 4         int col = grid[0].length;
 5         int[][] dp = new int[row][col];
 6         if (row == 0 || col == 0)                                  //空陣列
 7             return 0;
 8         dp[0][0] = grid[0][0];
9 for (int i = 1; i < row; i++){ //設定第1列 10 dp[i][0] = dp[i - 1][0] + grid[i][0]; 11 } 12 for (int i = 1; i < col; i++){ //設定第1行 13 dp[0][i] = dp[0][i - 1] + grid[0][i]; 14 }
15 for (int i = 1; i < row; i++){ //遍歷其餘位置 16 for (int j = 1; j < col; j++){ 17 int up = dp[i - 1][j] + grid[i][j]; //從上移動到當前節點 18 int left = dp[i][j - 1] + grid[i][j]; //從左移動到當前節點 19 dp[i][j] = (up < left) ? up : left; //
比較去最小值 20 } 21 } 22 return dp[row - 1][col - 1]; 23 } 24 }

解題思路:

這是一道經典的動態規劃題目,由於移動方向為向右與向下,說明除了第一行第一列以外,其餘點的對應最小路徑和,只可能是從左移動至當前位置的路徑和,或是從上方移動至當前位置的路徑和。我們使用二維陣列dp[row][col]儲存所有點的對應路徑和情況。

用up,left分別儲存從上,與從左的兩種情況,顯然動態方程為dp[i][j] = (up < left) ? up : left;

注意點:

  • 對於第一列,由於其沒有左方元素,所以dp值為dp[i - 1][0] + grid[i][0]
  • 對於第一行,由於其沒有上方元素,所以dp值為dp[0][i - 1] + grid[0][i]

空間複雜度:O(M*N),M,N為矩陣的行數與列數

時間複雜度:O(M*N)

優化:

我們發現,事實上每一行的元素的dp值,實際上只使用到了上一行的dp值與該行的前一位dp值,所以可以通過設定一維陣列dp[col],優化空間複雜度。

 1 class Solution {
 2     public int minPathSum(int[][] grid) {
 3         int row = grid.length;                    
 4         int col = grid[0].length;
 5         int[] dp = new int[col];
 6         if (col == 0)                                            //陣列為空
 7             return 0;
 8         dp[0] = grid[0][0];                                   
9
for (int i = 1; i < col; i++){ //設定第一行的dp 10 dp[i] = dp[i - 1] + grid[0][i]; 11 } 12 for (int i = 1; i < row; i++){ //遍歷其餘行 13 dp[0] = dp[0] + grid[i][0]; //每行開始為上一行+當前值 14 for (int j = 1; j < col; j++){ 15 int left = dp[j - 1] + grid[i][j]; //從左處移動到當前節點 16 int up = dp[j] + grid[i][j]; //從上方移動到當前節點上 17 dp[j] = (left < up) ? left : up; //取最小值 18 } 19 } 20 return dp[col - 1]; 21 } 22 }

解題思路:

同樣,先設定第一行的dp值。在通過迴圈遍歷,對於每個節點來說,還未計算時,對應的dp[j]儲存的是上方節點的情況,而dp[j -1]則對應的是左方節點的情況,所以我們只需改變先前演算法,使left = dp[j -1] + grid[i][j], up = dp[j] + grid[i][j]。最後修改dp[j]為兩者中的最小值即可。

注意點:

同樣,第一行與第一列需特殊處理。

  • 第一行,為dp[i - 1] + grid[0][i]
  • 第一列,為dp[i] + grid[i][0]

空間複雜度:O(N),N為矩陣的列數

時間複雜度:O(M*N)

題後總結:

優:對於經典的動態規劃熟練掌握,能迅速的解出,並進行一定的優化

差:程式碼部分仍可精簡,如使用Math.min