LeetCode[62] 不同路徑(DP)

本題目算是面試比較常見的了,主要考察對算法的理解,最優的解法是動態規劃,本篇寫一下本題的動態規劃思路和解法。

題目描述

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

示例一:

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

  1. 向右 -> 向右 -> 向下
  2. 向右 -> 向下 -> 向右
  3. 向下 -> 向右 -> 向右

示例二:

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

提示:

  • 1 <= m, n <= 100
  • 題目數據保證答案小於等於 2 * 10^9 (int類型)

題解思路

  1. 暴力法:使用 DFS 遍歷,從 (1,1)-> (m, n),當到達右下角時,計數加一,直到遍歷結束。只能解決一部分用例,會執行超時,時間複雜度 O(N^2)
  2. 動態規劃:開闢新的狀態空間,保存每個點的狀態值,該狀態值表示到達該點所能走的路數。最終到達右下角時,該點所記錄的路數就是總共的不同路徑數。因爲只需要遍歷一次二維數組的狀態值,因此時間複雜度爲 O(N)

如何求每個點的狀態值呢?這個問題就用到了數學歸納法了,觀察可得:
當 m = 1, n = 1 時,起點不用向右和向下就已到達,路數爲 1;
當 m = 1, n = 2 時,起點只能向下一步到達目標點,路數爲 1;
當 m = 2, n = 1 時,起點只能向右一步到達目標點,路數爲 1;
當 m = 2, n = 2 時,起點可以往右一步再往下一步,或者先往下再往右到達目標點,路數爲 2;
當 m = 2, n = 3 時,起點可以往下兩步再往右一步,或者到達點(2,2)再往下一步,而到達點(2,2)的路數爲 2,因此到達目標點的路數總共 爲 3;
以此類推,可以發現規律,到達點(m, n)的路數是(m - 1, n)的路數加(m, n - 1)的路數和,即:status[m][n] = status[m - 1][n] + status[m][n-1](狀態轉移方程)

代碼實現

遞歸代碼
int status[101][101] = {0};
int uniquePaths(int m, int n)
{
    if(m <= 0 || n <= 0) {
        return 0;
    }
    if(m == 1 || n == 1) {
        return 1;
    }
    // 當該點狀態值 > 0 時,說明已經計算過路徑數,無需重複計算
    if(status[m][n] > 0) {
        return status[m][n];
    }
    status[m - 1][n] = uniquePaths(m - 1, n);
    status[m][n - 1] = uniquePaths(m, n - 1);
    status[m][n] = status[m - 1][n] + status[m][n - 1];
    return status[m][n];
}
迭代代碼
int uniquePaths(int m, int n)
{
    int status[101][101] = {0};
    int i, j;
    for(i = 1; i <= m; i++) {
        for(j = 1; j <= n; j++) {
            if(i == 1 || j == 1) {
                status[i][j] = 1;
            }
            else {
                status[i][j] = status[i - 1][j] + status[i][j -1];
            }
        }
    }
    return status[m][n];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章