算法-不同路徑問題

1、不同路徑(I)

62. 不同路徑

本問題是動態規劃的一個比較經典的題目,和跳臺階問題本質上是一樣的,只是跳的位置不一樣而已。
在這裏插入圖片描述

	一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記爲“Start” )。
	機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記爲“Finish”)。
	問總共有多少條不同的路徑?

例如,上圖是一個7 x 3 的網格。有多少可能的路徑?

示例 1:

輸入: m = 3, n = 2
輸出: 3
解釋:
從左上角開始,總共有 3 條路徑可以到達右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:

輸入: m = 7, n = 3
輸出: 28
 

提示:

1 <= m, n <= 100
題目數據保證答案小於等於 2 * 10 ^ 9

1.1 初步解

由於只能向右或者向下,那麼在機器人經過某個點的時候就會有這樣的關係

dp[i][j]=dp[i-1][j]+dp[i][j-1];

即當前位置的方案數爲左側方案數和上側方案數之和。

那初始條件我們怎麼確定呢?

由於這個機器人走路比較獨特,所以其實我們可以它走到第一行或者第一列的每個位置,都只有一種方案:一條路走到黑。爲此,我們將其初始化爲1即可

public int uniquePaths(int m, int n) {
	int[][]dp=new int[m][n];//表示到達每個位置的方案數
	for(int i=0;i<m;i++){
		dp[m][0]=1;
	}
	for(int i=0;i<n;i++){
		dp[0][n]=1;
	}
	for(int i=1;i<m;i++){
		for(int j=1;j<n;j++){
			dp[i][j]=dp[i-1][j]+dp[i][j-1];
		}
	}
	return dp[m-1][n-1];
}

我們還可以對其進一步優化,

1.2 時間優化

我們使用了兩個循環來初始化dp數組,其實這是不必的,我們只需要在遍歷矩陣的時候判斷訪問的是不是左邊界和上邊界,將左邊界和上邊界置爲1即可。

    public int uniquePaths(int m, int n) {
        if(m==1||n==1){
            return 1;
        }
        int[][]dp=new int[m][n];//表示到達每個位置的方案數
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                if(i-1==0){
                    dp[0][j]=1;
                }
                if(j-1==0){
                    dp[i][0]=1;
                }
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }

2、不同路徑(II)

63.不同路徑(||)

機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記爲“Finish”)。

現在考慮網格中有障礙物。那麼從左上角到右下角將會有多少條不同的路徑?



網格中的障礙物和空位置分別用 1 和 0 來表示。

說明:m 和 n 的值均不超過 100。

示例 1:

輸入:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
輸出: 2
解釋:
3x3 網格的正中間有一個障礙物。
從左上角到右下角一共有 2 條不同的路徑:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右

這次我們的路徑裏出現了障礙物,不過這不是什麼問題。

轉移方程還是上面的

dp[i][j]=dp[i-1][j]+dp[i][j-1];

只不過我們需要對障礙物加一個條件,如果i,j的位置爲障礙物,那麼我們將dp[i][j]標註爲0,這樣就可以了。


    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
    	int m=obstacleGrid.length,n=obstacleGrid[0].length;
		int[][]dp=new int[m][n];//表示到達每個位置的方案數
		for(int i=0;i<m&&(obstacleGrid[i][0]!=1);i++){
			dp[i][0]=1;
		}
		for(int i=0;i<n&&(obstacleGrid[0][i]!=1);i++){
			dp[0][i]=1;
		}
		for(int i=1;i<m;i++){
			for(int j=1;j<n;j++){
				if(obstacleGrid[i][j]==1){
					dp[i][j]=0;
				}else{
					dp[i][j]=dp[i-1][j]+dp[i][j-1];
				}
			}
		}
		return dp[m-1][n-1];
    }

上面的空間複雜度還可以再優化一下,不過寫出來就不太優雅了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章