[LeetCode]19. 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.

 

解:1:从左上角走到右下角需要向下移动m-1步,向右移动n-1步。每次移动前,判断是否还能向下或者向右移动。在向下或者向右移动一步后,接下来的移动过程可以递归调用。

class Solution {
public:
    int uniquePaths(int m, int n) {
        int i = m, j = n;
        int res = 0;
        if (i <= 1 || j <= 1)
        {
            res += 1;
            return res;
        }
        else if (i > 1 && j > 1)
            res += uniquePaths(i - 1, j) + uniquePaths(i, j - 1);
        else if (i > 1 && j <= 1)
            res += uniquePaths(i - 1, j);
        else if (i <= 1 && j > 1)
            res += uniquePaths(i, j - 1);
    }
};

换个思路考虑,如果某次移动到了最下行或者最右行,则接下来的移动没有选择,只有一条路径了。因此可以改进程序如下所示:

class Solution {
public:
    int uniquePaths(int m, int n) {
        if(m == 1 || n == 1)
            return 1;
        else
            return uniquePaths(m - 1, n) + uniquePaths(m, n - 1);
    }
};

因为递归调用,在m,n较大时会出现Time Limit Exceeded

 

解法2:从左上角走到右下角需要向下移动m-1步,向右移动n-1步,一共移动m+n-2步。因为中间没有任何障碍,所以很简单:即是在m+n-2步中取m-1步向下,或者是在m+n-2步中取n-1步向右即可。即是求组合数C(m+n-2,m-1)或者C(m+n-2,n-1)。因为m+n-2=m-1+n-1,假设n>m,则C(m+n-2,m-1)=(m+n-2)*(m+n-3)*...*n/(m-1)!。

class Solution {
public:
    int uniquePaths(int m, int n) {
        int res = 0;
        int a = m > n ? m : n;
        int b = m + n - a - 1;
        int sum = m + n - 2;
        long long p1 = 1, p2 = 1;

        while (sum >= a)
            p1 =  p1 * sum--;
        while (b >= 1)
            p2 = p2 * b--;
        res = p1 / p2;
        return res;
    }
};

 

解法3:动态规划。移动到[i,j]的路径path[i,j]=path[i-1,j]+path[i,j-1](0<i<m,0<j<n),初始化path[i][0]=1,path[0][j]=1(0<=i<m,0<=j<n)。最后path[m-1][n-1]即是最终结果。时间空间复杂度都是O(mn)。

class Solution {
public:
    int uniquePaths(int m, int n) {
        int res = 0;
        if(m <= 0 || n <= 0)
            return res;
        
        int** path = new int*[m];
        for(int i = 0; i < m; i++)
            path[i] = new int[n];
        
        for(int i = 0; i < m; i++)
            path[i][0] = 1;
        for(int i = 0; i < n; i++)
            path[0][i] = 1;
        
        for(int i = 1; i < m; i++)
        {
            for(int j = 1; j < n; j++)
                path[i][j] = path[i - 1][j] + path[i][j - 1];
        }
        res = path[m - 1][n - 1];
        
        for(int i = 0; i < m; i++)
            delete[] path[i];
        delete[] path;
        
        return res;
    }
};

利用滚动数组可以将空间复杂度降为O(n):

class Solution {
public:
    int uniquePaths(int m, int n) {
        int res = 0;
        if(m <= 0 || n <= 0)
            return res;
        
        int* path = new int[n];
        for(int i = 0; i < n; i++)
            path[i] = 1;
        for(int i = 1; i < m; i++)
        {
            for(int j = 1; j < n; j++)
                path[j] += path[j - 1];
        }
        res = path[n - 1];
        delete[] path;
        
        return res;
    }
};

外层循环使得path保存了移动到当前行的上一行所有位置的路径数目,因此内层循环只需要在加上当前列的左边列的路径数目即可。

posted @ 2015-10-09 19:40  AprilCheny  阅读(194)  评论(0编辑  收藏  举报