代码随想录 28(动态规划)

力扣 62.不同路径


思路

  1. dpm n -----> 走到 方格m n 的总共路径 dpmn

  2. dpmn = dpm--n + dpmn--

  3. 初始值00不用管,12 = 1,21 = 1。

  4. 遍历顺序从上到下,从左到右

  5. 举例推导:m=3,n=2

    |---|---|
    | | 1 |
    | 1 | 2 |
    | 1 | 3 |

从举例推导时候可以发现,还有一些特殊情况没有想到,例如最上面一行和最左列怎么办?没有m--,没有n--。然后注意m和n的一个边界值。所以初始值应该是第一行和第一列的路径都为1。


解法

java 复制代码
    public int uniquePaths(int m, int n) {

        if (m == 1 || n == 1) {
            return 1;
        }

        int[][] dp = new int[m + 1][n + 1];
        // 初始化第1行 = 1
        Arrays.fill(dp[1], 1);
        // 初始化第1列 = 1
        for (int i = 0; i <= m; i++) {
            dp[i][1] = 1;
        }

        for (int i = 2; i <= m; i++) {
            for (int j = 2; j <= n; j++) {

                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }

        return dp[m][n];
    }

时间复杂度:O(m*n)

空间复杂度: O(m*n)

可以进行优化: 压缩为一维数组,那么空间复杂度是O(n)。

这里不做优化的解法设计到数学问题


力扣 63.不同路径②


思路

其实这道题思路跟上一题没什么太大的不同,无非就是多一个障碍物的判断。但是需要主要的点是上一道题为了容易理解,坐标直接从1开始,这道题坐标需要从0开始,因为题目给定数组,数组是从0开始。


错误分析

java 复制代码
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {

        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;

        //如果在起点或终点出现了障碍,直接返回0
        if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) {
            return 0;
        }

        int[][] dp = new int[m][n];
        // 初始化第1行 = 1
        for (int i = 0; i < n; i++) {
            if (obstacleGrid[0][i] != 1) {
                dp[0][i] = 1;
            }
        }
        // 初始化第1列 = 1
        for (int i = 0; i < m; i++) {
            if (obstacleGrid[i][0] != 1) {
                dp[i][0] = 1;
            }
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] != 1) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }

        return dp[m-1][n-1];
    }
  1. 一定需要注意下标和上一题的不一样,这一题下标是从0开始,直接复制上一题答案修改时候一定注意所有设计下标的地方。
  2. 这里遇到障碍物跳过,其实不对的,当 obstacleGrid =\[0,1,0,0] 时候,会导致结果输出还是1,因此初始值的判断条件应该放在循环条件里面,初始值遇到障碍区直接跳出循环。
  3. 需要注意的是如果在起点或终点出现了障碍,直接返回0

解法

java 复制代码
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {

        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;

        //如果在起点或终点出现了障碍,直接返回0
        if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) {
            return 0;
        }

        int[][] dp = new int[m][n];
        // 初始化第1行 = 1
        for (int i = 0; i < n && obstacleGrid[0][i] != 1; i++) {
                dp[0][i] = 1;
        }
        // 初始化第1列 = 1
        for (int i = 0; i < m && obstacleGrid[i][0] != 1; i++) {
                dp[i][0] = 1;
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] != 1) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }

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

时间复杂度:O(m*n)

空间复杂度: O(m*n)

可以进行优化: 压缩为一维数组,那么空间复杂度是O(n)。

这里不做优化的解法设计到数学问题


力扣 96.不同的二叉搜索树


思路

首先先了解什么是二叉搜索树:

**二叉树:**每个节点最多只有左右两个两个子节点的树结构。

**二叉搜索树:**一棵二叉树,且对树上任意一点都有:左子树 < 根 <右子树。左右子树也是二叉搜索树。

  1. 确定动态数组和数组的下标含义
  2. 确定递推公式
  3. 确定初始值
  4. 确定遍历顺序
  5. 举例推导
相关推荐
UIU1146 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场6 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi6 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David7 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院8 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng8 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
j7~11 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py12 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing12 小时前
LeetCode100 42.接雨水
java·算法·leetcode
域限奇点访客13 小时前
用AI生成问卷的网站怎么选?看题目录入结构、题型映射和生成后的校验
算法