LeetCode筆記——64最小路徑和
題目:
給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。
說明:每次只能向下或者向右移動一步。
示例:
輸入: [ [1,3,1], [1,5,1], [4,2,1] ] 輸出: 7 解釋: 因為路徑 1→3→1→1→1 的總和最小
思路:和63,62題的思路一致,都是使用動態規劃的思想。參考網上大神的程式碼,還有一種將儲存空間變為一個一維陣列的。思路是一樣的。
程式碼:
程式碼1:
class Solution {
public int minPathSum(int[][] grid) {
int rows = grid.length;
int cols = grid[0].length;
int[][] dp = new int[rows][cols]; //用來記錄當前節點到左上角的最短路徑
dp[0][0]= grid[0][0];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(i==0&&j==0)continue;
else if(i==0&&j!=0){
dp[i][j]=dp[i][j-1]+grid[i][j]; //對第一行的處理
}
else if(i!=0&&j==0){
dp[i][j]=dp[i-1][j]+grid[i][j]; //對第一列的特殊處理
}
else
dp[i][j]=Math.min(dp[i-1][j], dp[i][j-1])+grid[i][j]; //對於普通位置,等於本身的值加上上面或者左邊之間的最小值
}
}
return dp[rows-1][cols-1];
}
}
程式碼2:
public static int shortestRoad1(int arr[][]) {
int dp[]=new int[arr[0].length];
dp[0]=arr[0][0];
for(int j=1;j<arr[0].length;j++) {
dp[j]=dp[j-1]+arr[0][j]; //求出第一行的dp
}
for(int i=1;i<arr.length;i++) {
dp[0]=arr[i][0]+dp[0]; //dp[0]代表每一行最左邊的dp,
//後一行的dp覆蓋前一行的dp
for(int j=1;j<arr[0].length;j++) {
dp[j]=Math.min(dp[j-1]+arr[i][j], dp[j]+arr[i][j]);
}
}
return dp[arr[0].length-1];
}
執行最快的程式碼:
使用了遞迴的思想。好像有點像深度優先搜尋的感覺。超出邊界返回最大值;到達終點(右下角的位置);之前已經計算過該值(算是被標記過)。這三種情況返回,剩下的請求繼續遞迴。
class Solution { private int[][] grid; private int sum; private int[][] temp; public int minPathSum(int[][] grid) { this.grid=grid; temp=new int[grid.length][grid[0].length] ; int x=0; int y=0; return minPath(0,0); } private int minPath(int x,int y){ if(x==grid.length-1&&y==grid[0].length-1){ return grid[x][y]; } if(x>grid.length-1||y>grid[0].length-1){ return Integer.MAX_VALUE; } if(temp[x][y]!=0){ return temp[x][y]; } temp[x][y]=grid[x][y]+Math.min(minPath(x+1,y),minPath(x,y+1)); return temp[x][y]; } }