代码随想录算法训练营(动态规划2)| 62.不同路径 & 63. 不同路径 II

发布于:2024-02-25 ⋅ 阅读:(51) ⋅ 点赞:(0)

62.不同路径

本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。
leetcode题目链接
题目链接/文章讲解
视频讲解

二叉树的深度搜索,找到总共有几个叶子节点
这个想理解好难啊
//每个节点都是从左向右,然后回溯,从上向下
//

class Solution {
private:
    int dfs(int i, int j, int m, int n) {
        if (i > m || j > n) return 0; // 越界了
        if (i == m && j == n) return 1; // 找到一种方法,相当于找到了叶子节点
        int left = dfs(i + 1, j, m, n);// i 向右移动,后递归
        //这里有I回溯,j +1 
        int right = dfs(i, j + 1, m, n);
        return left + right;
    }
public:
    int uniquePaths(int m, int n) {
        return dfs(1, 1, m, n);
    }
};

动态规划五步曲

  1. 确定dp数组(dp table)以及下标的含义
    dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

  2. 确定递推公式
    想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。
    此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。

那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]

  1. dp数组的初始化
    如何初始化呢,首先dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。
    for (int i = 0; i < m; i++) dp[i][0] = 1;
    for (int j = 0; j < n; j++) dp[0][j] = 1;
    4.遍历顺序是从前往后遍历
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][j-1] + dp[i -1][j];
            }
        }

        return dp[m-1][n-1];
    }
};

63. 不同路径 II

leetcode题目链接
题目链接/文章讲解
视频讲解

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>> dp(m, vector<int>(n, 0));

        //如果起始位置和重点位置有障碍,没有路径可以到达
        if(obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1) {
            return 0;
        }
        for(int i = 0; i < m && obstacleGrid[i][0] != 1; i ++) {
            dp[i][0] = 1;
        }
        for(int j = 0; j < n && obstacleGrid[0][j] != 1; j++) {
            dp[0][j] = 1;
        }

        for(int i = 1; i < m; i ++) {
            for(int j = 1; j < n; j ++) {
                //如果下标对应的位置有障碍说明这条路线不能到达终点所以需要跳过
                if(obstacleGrid[i][j] == 1) continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        //下标从0开始所以都需要减一
        return dp[m-1][n-1];
    }
};

网站公告

今日签到

点亮在社区的每一天
去签到