原题目描述
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 7 x 3 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
Example 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
Example 2:
Input: m = 7, n = 3
Output: 28
题目大意
对该题进行简化表述就是:有一个简单的矩阵,起点为左上角,终点为右下角,每次行进只能向下或者向右,问有多少条从起点到终点的路径,输入为矩阵的行数和列数,输出为路径数量。
解题思路
该题目可以采用分治算法,每走到矩阵的一个点,我们都有两种走法,向下或者向右,而当走到矩阵的边界,右边界或者下边界,我们就能确定一条唯一路(因为接下来你只能走同一个方向了),所以采用函数递归,我们可以得到如下代码(此代码不能通过):
int uniquePaths(int m, int n) {
if (m == 1 || n == 1) // 到达边界点
return 1
// 未到达边界点,向两个方向继续递归
return uniquePaths(m-1, n) + uniquePaths(n-1, m);
}
该代码使用了尾递归的形式,因为向右和向下的步数是有限的,分别为m-1,和 n-1,所以我们每到一个非边界点,便向这两个方向行进(返回往这两个方向行进到达终点的路径之和),对应的步数-1,当m或n为1时,说明我们到达了某一边界点,这时也确定了一条唯一的路径,返回1。
然而,该代码虽然正确,但并不完善,当m,n的值过大时会造成TL,因为会造成冗余的计算,如到达(m = 10, n = 10)的点,那么接下来,我们会到达(m = 9, n = 10)和 (m = 10, n = 9),而这两个点后边都会经过(m = 9, n = 9)的点,那么我们会计算两次uniquePaths(9, 9),而越到底部,这样重复的计算就会越多,最终造成运算时间过大。
所以我们需要把这些计算得到的值存起来,下次如果需要使用这些值,无需再次计算,就直接得到该值,便能大大减少运算时间了。实现代码如下:
C++实现代码
// 二维数组用来存储点(m, n)到达终点的路径数,初始均为0
int a[101][101] = {};
class Solution {
public:
int uniquePaths(int m, int n) {
if (m == 1 || n == 1) // 到达边界点
return 1;
else if (a[m][n]) // 如果存在已经计算好的值,便直接取出
return a[m][n];
else {
// 无存在计算好的值,计算并存储放入数组
a[m][n] = uniquePaths(m-1, n) + uniquePaths(n-1, m);
return a[m][n];
}
}
};