[LeetCode] Unique Paths 题解

前言

Unique Paths应该说是LeetCode动态规划系列中很亲民的一道题了(AC率比较高)。实际上,Dynamic Programming的题目一般关键都在于想出递推关系,成功写出准确的循环解法。

题目

题目链接:https://leetcode.com/problems/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.

分析

题意很清楚,就是走格子。只可以向下走或者向右走,从mxn大小的格子地图上,由左上角一直走到右下角。对应于每组m,n大小的地图,求出所有不同的走法(Unique Paths)的个数。

对于这个题,求解状态转移方程,会有一种相当轻松的思路。那就是假设这个粉红色的Robot已经走到了终点的左侧格子(称为A)或者上侧格子(称之为B),如果从起点走到A或者走到B的走法个数已经计算出来了,分别为numsA 和 numsB,显然,走向终点的Unique Paths数就是numsA + numsB(因为从起点走向终点最终都势必通过A点和B点)。
那么稍微扩展一下,对于不在地图最上方一行和最左侧一列的所有格子,都有这个规律。而对于边际上的格子(最上方一行和最左侧一列),由起点走向它们都只有唯一一条路径(即只有一种走法)。我们可以使用一个二维数组来存储走向不同格子的Unique Paths个数。想通了这一层,代码就会很好写了。

代码

把上述分析简单地转化为代码实现,得到:

class Solution {
public:
    int uniquePaths(int m, int n) {
        int dp[100][100];//m,n<100
        for (int i = 0; i < n; i++) dp[i][0] = 1;//最左侧一列的格子
        for (int j = 0; j < m; j++) dp[0][j] = 1;//最上方一列的格子
        for (int i = 1; i < n ; i++) {
            for (int j = 1; j < m; j++) {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
    return dp[n-1][m-1];//走向终点的Unique Paths个数
    }
};

把上面的代码稍微简化一下:

class Solution {
public:
  int uniquePaths(int m, int n) {
    vector<vector<int>> Array(m, vector<int>(n,1));
    for (int i = 1; i < m; i++) {
      for (int j = 1; j < n; j++) {
        Array[i][j] = Array[i-1][j] + Array[i][j-1];
      }
    }
    return Array[m-1][n-1];
  }
};

当然,对于这道题,还有一种公式法——直接使用组合数学的结论来计算。

class Solution {
    public:
        int uniquePaths(int m, int n) {
            int N = n + m - 2;// how much steps we need to do
            int k = m - 1; // number of steps that need to go down
            double res = 1;
            // here we calculate the total possible path number 
            // Combination(N, k) = n! / (k!(n - k)!)
            // reduce the numerator and denominator and get
            // C = ( (n - k + 1) * (n - k + 2) * ... * n ) / k!
            for (int i = 1; i <= k; i++)
                res = res * (N - k + i) / i;
            return (int)res;
        }
    };

你可能感兴趣的:(算法与数据结构,LeetCode)