62:不同路径(C++)

题目地址:https://leetcode-cn.com/problems/unique-paths/

题目描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。问总共有多少条不同的路径?

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 10 ^ 9

题目示例

示例 1:

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:

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

解题思路

分析题目可知,到达终点Finish,可以看作是终点的前一列或者前一行的格子,递归式具体可表示为arr[m][n]=arr[m-1][n]+arr[m][n-1]。知道有些同学看不明白,分享一个图,如下

思路1:递归。对题目给的问题采用自顶向下的思想,拆分为若干子问题求解,但存在子问题的重复求解问题,时间复杂度O(2^mn);

思路2:记忆化搜索。该方法是对递归的方法进行优化,使用数组存储已经求解过的路径避免重复,时间复杂度O(nn),空间复杂度O(mn);

思路3:动态规划。将原问题拆分为若干子问题,然后对每个子问题进行求解,并将结果进行保存,从而避免了子问题的重复求解,时间复杂度O(mn),空间复杂度O(mn)。在这里,我们使用二维数组dp来存储最终结果,其中dp[i][j]表示从起点(0,0)走到(i,j)的路径数。根据题目可知,机器人只能向下或者向右,所以dp[i][j]的值就等于第i行第j列这个格子上面的那个格子的路径数加上左边那个格子的路径数,即状态转移方程为dp[i][j]=dp[i-1][j]+dp[i][j-1],因为这两个格子都可以走到第i行第j列的这个格子。

思路4:对思路3进行优化,主要是优化空间复杂度,因为在思路3中dp数组存储了所有格子的路径信息,我们可以使用一维数组dp来存储最终结果,即当前行格子的信息,其中dp[j]=dp[j]+dp[j-1]为递归表达式。通俗讲,也就是将每一行当作一个动态规划处理,第一行初始化为全1,即路径数为dp[0]=1,然后dp[1]为第二行路径数,即j=1时的路径数,而dp[1]等于上一行数加上当前行元素的值,即dp[1]=dp[0]+dp[1]=2,j=2时,dp[2]=上一行元素的值dp[2]+dp[2-1]=1+2=3,以此类推,可得dp[j]=dp[j]+dp[j-1]。

相似题目还有63、980。

程序源码

思路1

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

思路2

class Solution {
public:
    int arr[101][101] = {0};
    int uniquePaths(int m, int n) {
        if(m <= 0 || n <= 0) return 0;
        if(m == 1 && n == 1) return 1;
        if(arr[m][n] > 0) return arr[m][n];
        arr[m - 1][n] = uniquePaths(m - 1, n);
        arr[m][n - 1] = uniquePaths(m, n - 1);
        arr[m][n] = uniquePaths(m - 1, n) + uniquePaths(m, n - 1);
        return arr[m][n];
    }
};

思路3

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for(int i = 0; i < m; i++) 
        {
            dp[i][0] = 1; //初始化第一列路径
        }
        for(int j = 0; j < n; j++)
        {
            dp[0][j] = 1; //初始化第一行路径
        }
        for(int i = 1; i < m; i++)
        {
            for(int j = 1; j < n; j++)
            {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; //状态转移方程
            }
        }
        return dp[m - 1][n - 1]; //到达Finish格子的路径数目
    }
};

空间复杂度优化

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<int> dp(n, 1);
        for(int i = 1; i < m; i++)
        {
            for(int j = 1; j < n; j++)
            {
                dp[j] += dp[j - 1]; //状态转移方程
            }
        }
        return dp[n - 1]; //到达Finish格子的路径数目
    }
};

参考文章

https://leetcode-cn.com/problems/unique-paths/solution/java-jian-dan-ming-liao-de-dong-tai-gui-hua-qiu-ji/

----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/13531496.html