1. 程式人生 > >Leetcode演算法——62、不重複路徑(unique paths)

Leetcode演算法——62、不重複路徑(unique paths)

一個機器人位於一個m*n的網格的左上角。

它每次只能向下或向右移動一格。它試圖到達網格的右下角。

求有多少種不重複的路徑?

備註:
m和n最大為100.

示例1:

Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right

示例2:

Example 2:
Input: m = 7, n = 3
Output: 28

思路

1、數學法

路徑數是可以通過數學公式直接計算出來的。

對於m*n的網格,從左上角到右下角,無論怎麼走,都必定包含 m-1 次右移和 n-1 次下移。

因此問題轉換為:將 m-1 個黑球和 n-1 個白球串成長度為 m+n-2 的佇列,問排列方式有幾種。

這是一個排列組合文體,方法為:從 m+n-2 個空位置中,選出 m-1 個位置,放黑球,其他位置放白球。

因此排列方式有 C

m + n 2 m 1
= ( m + n 2 ) ! / [ ( m 1 ) ! ( n 1 ) ! ] C_{m+n-2}^{m-1} = (m+n-2)! / [(m-1)!(n-1)!] 種。

2、動態規劃

設左上角座標為(0,0),右下角座標為(m,n)。

則走到(m,n)的路徑數 = 走到(m-1,n)的路徑數 + 走到(m,n-1)的路徑數。

這是因為:

  • 要想走到(m,n),必定會經過(m-1,n)或(m,n-1)的其中一個,因此需要相加。
  • 經過其中一個之後,只有一種走法可以到達終點,沒有其他選擇,因此不用乘以係數。
  • 經過其中一個之後,必定不會經過另外一個,不會有重疊,因此不用減去他們的交集。

python實現

import math
def uniquePaths1(m, n):
    """
    :type m: int
    :type n: int
    :rtype: int
    數學法。
    """
    return int(math.factorial(m+n-2) / math.factorial(m-1) / math.factorial(n-1))

def uniquePaths2(m, n):
    """
    :type m: int
    :type n: int
    :rtype: int
    動態規劃。
    """
    dp = [[1] * n for _ in range(m)]
    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = dp[i-1][j] + dp[i][j-1]
    return dp[-1][-1]
    

if '__main__' == __name__:
    m, n = 7, 3
    print(uniquePaths2(m, n))