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

文章讲述了使用动态规划方法解决二叉树中找到从起点到叶子节点的不同路径问题,以及处理带有障碍的网格中独特路径的求解过程。重点介绍了dp数组的定义、递推公式和初始化步骤。
摘要由CSDN通过智能技术生成

62.不同路径

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

二叉树的深度搜索,找到总共有几个叶子节点的值是dp[m][n]
二叉树的节点定义:二叉树的每一个节点的左节点是向右移动,右节点是向下移动。
每一层的含义:这样每一层就是向下,向右移动的所有情况,这里也是回溯算法的用法。
每向下一层含义:每向下一层,就是向下,向右各移动一步,对应数组就是dp[i][j],就是i + 1 并且 j + 1
根节点到叶子节点的路径的含义:每条路径就是到目标值的所有路径

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]过来的,从上边过来的一定是从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];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值