1. 程式人生 > >LeetCode64題:最小路徑和

LeetCode64題:最小路徑和

思路:

 題目要求的是從左上角即[0,0]位置開始,到右下角即[m-1,n-1]位置為止的最小路徑和。倒過來思考的話,對於右下角[m-1,n-1]來說,它的上一步只有兩個位置即[m-2,n-1]和[m-1,n-2],因此問題就可以轉化為求從[0,0]到這兩個位置的路徑和的較小值,即狀態轉移公式為:min ( arr[m-1][n-1] ) = min ( arr[m-1][n-1]+min( arr[m-2][n-1] ),arr[m-1][n-1]+min( arr[m-1][n-2] )),因此可以很容易的用遞迴方式求解。

解法一:遞迴法

public int minPathSum(int[][] grid) {
        return help1(grid,grid.length-1,grid[0].length-1);
    }
public int help1(int[][] arr,int row,int col){
        if(row == 0 && col == 0){
            return arr[row][col];
        }
        if(row != 0 && col == 0){
            return arr[row][col]+help1(arr,row-1,col);
        }
        if(row == 0 && col != 0){
            return arr[row][col]+help1(arr,row,col-1);
        }
        return arr[row][col]+Math.min(help1(arr,row-1,col),help1(arr,row,col-1));
    }

但是遞迴法涉及到很多的重複計算,時間複雜度超時,因此需要換一種思路。剛才採用遞迴法時,考慮的是從後往前求解,那麼現在反過來,從前往後可不可以呢?如果能從前往後計算的話,那麼就可以依次求出從左上角到任意一個位置的最小路徑和了,因為要求的這個位置之前的兩個位置的最小值已經知道了,這樣就不存在重複計算(即動態規劃法)。那麼這種思路能不能實現呢?接著思考,對於二維陣列來說,在邊界上的位置,它的上一步只有一個,而處在中間位置的才有兩個。而對二維陣列進行遍歷的時候,就是從上到下從左到右的遍歷的,跟路徑的行走規則一致,那麼就可以在遍歷的時候直接求出每個位置的最小路徑和了。

解法二:動態規劃法

public int minPathSum(int[][] grid) {
        return help(grid);
    }
    public int help(int[][] arr){
        int row = arr.length;
        int col = arr[0].length;
        for(int i=0;i<row;i++){
        	for(int j=0;j<col;j++){
        		if(i == 0 && j == 0){
        			continue;
        		}
        		if(i != 0 && j != 0){
        			arr[i][j] += Math.min(arr[i-1][j], arr[i][j-1]); 
        		}else if(i == 0){
        			arr[i][j] += arr[i][j-1]; 
        		}else{
        			arr[i][j] += arr[i-1][j];
        		}
        	}
        }
        return arr[row-1][col-1];
    }