Unique Paths

一. Unique Paths

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

How many possible unique paths are there?

這裏寫圖片描述

Above is a 3 x 7 grid. How many possible unique paths are there?

Note: m and n will be at most 100.

Difficulty:Medium

TIME:12MIN

解法一(動態規劃)

這道題,按題目說的數據量,如果採用搜索來做,超時肯定超到天邊去了。

這道題可以用動態規劃來求解:

  • 如果只有一行,那麼當然只有一條路可以走,那麼可以設定一個數組爲[1,1,1,1,1,1,1],表示從該點到終點的所有可能路徑數。
  • 如果有兩行,我們會發現,第一行的路徑數變爲了[7,6,5,4,3,2,1],爲下面那一行所有可能路徑數的疊加值。
  • 同理,如果有三行,那麼第一行的路徑就是第二行路徑的疊加值,而第二行路徑爲最後一行路徑的疊加值。

因此,代碼如下:

int uniquePaths(int m, int n) {
    vector<int> v(n,1);
    while(m > 1) {
        for(int i = 1; i < n; i++)
            v[i] += v[i - 1];
        m--;
    }
    return v[n - 1];
}

代碼的時間複雜度爲O(mn)

解法二(公式求解)

既然每次向右走和每次向下走的選擇都會創造一條獨一無二的路徑,那麼我們可以把行走的路徑看出一個排列

比如其中一條路徑就可以表示爲[D,D,R,R,R,R,R,R],就是一直往下走,到底後就一直往右走。而且,任意兩個D和六個R的排列,都是一條獨一無二的路徑,所以,我們只要求出了兩個D和六個R的所有排列數,就相當於求解了3 x 7 grid的所有路徑數。

求全排列總數的公式爲(m+n)!/(m!n!)

int uniquePaths(int m, int n) {
    int big = max(m - 1, n - 1);
    int small = min(m - 1, n - 1);
    long result = 1;
    for(int i = 1, j = big + 1; i <= small; i++, j++) {
        result *= j;
        result /= i;
    }
    return (int)result;
}

代碼的時間複雜度爲O(min(n,m))

二. Unique Paths II

Follow up for “Unique Paths”:

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
[0,0,0],
[0,1,0],
[0,0,0]
]

The total number of unique paths is 2.

Note: m and n will be at most 100.

Difficulty:Medium

TIME:16MIN

解法(動態規劃)

題目改變之後應該是不能用公式來直接求解了,不過還是可以用動態規劃來求解。

上面說過是求疊加值,那是因爲第一題是第二題的一種特例,其實這道題的最優子結構具體來說可以描述爲:

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

也就是往右邊走以及往下走的所有路徑之和,而且如果該點爲障礙,那麼就直接把值設爲0即可。

其實這道題自己創建個數組可能會比較簡單(就是創建m+1行n+1列的數組),這樣處理的邊界情況會少很多,不過爲了節省空間,我還是使用了輸入的數組作爲動態規劃的數組。

int uniquePathsWithObstacles(vector<vector<int>>& grid) {
    int m = grid.size();
    int n = grid[0].size();
    /*初始化最後一行*/
    grid[m - 1][n - 1] = 1 - grid[m - 1][n - 1];
    for(int i = n - 2; i >= 0; i--) {
        grid[m - 1][i] = grid[m - 1][i] != 1 ? grid[m - 1][i + 1] : 0;
    }
    for(int i = m - 2; i >= 0; i--) {
        /*初始化該行最後一個點*/
        grid[i][n - 1] = grid[i][n - 1] != 1 ? grid[i + 1][n - 1] : 0;
        for(int j = n - 2; j >= 0; j--) {
            //dp過程
            grid[i][j] = grid[i][j] != 1 ? (grid[i][j + 1] + grid[i + 1][j]) : 0;
        }
    }
    return grid[0][0];
}

代碼的時間複雜度爲O(mn)

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