代码随想录算法训练营第三十九天| 62.不同路径、63.不同路径II

news2024/12/23 13:07:46

系列文章目录


目录

  • 系列文章目录
  • 62.不同路径
    • ①回溯算法(超时)
    • ②深度搜索(超时)
    • ③动态规划
  • 63. 不同路径 II
    • 动态规划


62.不同路径

①回溯算法(超时)

本质是穷举。

class Solution {
    int[] chose = new int[2];
    int col = 1;
    int row = 1;
    int res = 0;
    public int uniquePaths(int m, int n) {
        backTracking(m,n);
        return res;
    }

    public void backTracking(int m, int n) {
        //终止条件
        if (row > m || col > n) return;//越界
        if(row == m && col == n){
            res++;
            return;
        }
        for (int i = 0; i < chose.length; i++) {
            if (i == 0) {//向下
                row++;
            } else {//向右
                col++;
            }
            backTracking(m,n);
            //回溯
            if (i == 0) {//向下
                row--;
            } else {//向右
                col--;
            }
        }
    }
}

②深度搜索(超时)

用图论里的深搜,来枚举出来有多少种路径。
题目中说机器人每次只能向下或者向右移动一步,那么其实机器人走过的路径可以抽象为一棵二叉树,而叶子节点就是终点
在这里插入图片描述
此时问题就可以转化为求二叉树叶子节点的个数,代码如下:

class Solution {
    public int uniquePaths(int m, int n) {
        return dfs(1, 1, m, n);
    }

    public int dfs(int row, int col, int m, int n) {
        if (row > m || col > n) return 0;// 越界了
        if (row == m && col == n) return 1;// 找到一种方法,相当于找到了叶子节点
        return dfs(row + 1, col, m, n) + dfs(row, col + 1, m, n);
    }
}

在这里插入图片描述

③动态规划

机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。
动规五部曲:

  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][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。
  3. dp数组的初始化:dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。
  4. 确定遍历顺序:这里要看一下递推公式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]一定是有数值的。
  5. 举例推导dp数组。
class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        for (int i = 0; i < m; i++) {//行
            for (int j = 0; j < n; j++) {//列
                if (i == 0 || j == 0) {
                    dp[i][j] = 1;
                } else {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
}

在这里插入图片描述


63. 不同路径 II

动态规划

动规五部曲:

  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];
    这里需要注意一点,因为有了障碍,(i, j)如果就是障碍的话应该就保持初始状态(初始状态为0)。
  3. dp数组如何初始化:因为从(0, 0)的位置到(i, 0)的路径只有一条,所以dp[i][0]一定为1dp[0][j]也同理。但如果(i, 0) 这条边有了障碍之后,障碍之后(包括障碍)都是走不到的位置了,所以障碍之后的dp[i][0]应该还是初始值0。故代码里for循环的终止条件是,一旦遇到obstacleGrid[i][0] == 1的情况就停止dp[i][0]的赋值1的操作,dp[0][j]同理。
  4. 确定遍历顺序:从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出,一定是从左到右一层一层遍历,这样保证推导dp[i][j]的时候,dp[i - 1][j]dp[i][j - 1]一定是有数值。
  5. 举例推导dp数组。
class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        //初始化
        //如果在起点或终点遇到障碍物,直接返回0
        if (obstacleGrid[0][0] == 1 || obstacleGrid[m - 1][n - 1] == 1) return 0;
/*        for (int i = 0; i < m; i++) {//每行第一个元素
            // 如果第一行某个格子出现障碍物,则当前格子以及右边的所有格子都无法到达(直接使用初始化的默认值0即可)
            if (obstacleGrid[i][0] == 1) {
                break;
            }
            // 如果当前格子没有障碍物
            dp[i][0] = 1;
        }
        for (int i = 0; i < n; i++) {//每列第一个元素
            // 如果第一列某个格子出现障碍物,则当前格子以及下边的所有格子都无法到达(直接使用初始化的默认值0即可)
            if (obstacleGrid[0][i] == 1) {
                break;
            }
            // 如果当前格子没有障碍物
            dp[0][i] = 1;
        }*/
        //for循环的终止条件,一旦遇到obstacleGrid[i][0] == 1的情况就停止dp[i][0]的赋值1的操作,dp[0][j]同理
        for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;//每行第一个元素
        for (int i = 0; i < n && obstacleGrid[0][i] == 0; i++) dp[0][i] = 1;//每列第一个元素
        for (int i = 1; i < m; i++) {//每行
            for (int j = 1; j < n; j++) {//每列
                /*if (obstacleGrid[i][j] == 1) {
                    dp[i][j] = 0;
                } else {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }*/
                if (obstacleGrid[i][j] == 0) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
}

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1615426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CB2-2CARD之Debian(Bookworm)安装Gnome看CCTV

CB2-2CARD之Debian&#xff08;Bookworm&#xff09;安装Gnome看CCTV 1. 源由2. 需求3. Debian系统桌面3.1 系统安装3.2 磁盘扩容3.3 系统更新3.4 Gnome安装 4. 测试4.1 CCTV网页测试4.2 系统空闲测试4.3 Firefox CPU占用率测试 5. 总结 1. 源由 近些年来&#xff0c;随着国内…

笔试狂刷--Day4(滑动窗口+贪心)

大家好,我是LvZi,今天带来笔试狂刷--Day4 一.简写单词 1.题目链接:简写单词 2.题目分析: 一个简单的模拟 3.代码实现: 1.先整体读取,再处理 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public static void main(St…

35K的鸿蒙音视频开发岗位面经分享~

一个月前&#xff0c;阿里云在官网音视频终端 SDK 栏目发布适配 HarmonyOS NEXT 的操作文档和 SDK&#xff0c;官宣 MediaBox 音视频终端 SDK 全面适配 HarmonyOS NEXT。 此外&#xff0c;阿里云播放器 SDK 也在华为开发者联盟官网鸿蒙生态伙伴 SDK 专区同步上线&#xff0c;面…

【快速上手ESP32(基于ESP-IDFVSCode)】08-SPI

SPI SPI&#xff0c;全称Serial Peripheral Interface&#xff0c;即串行外设接口&#xff0c;是一种同步串行接口技术。它最初由Motorola公司推出&#xff0c;并在其MC68HCXX系列处理器上首次定义。SPI接口主要应用在EEPROM、FLASH、实时时钟、AD转换器&#xff0c;以及数字信…

【MySQL】InnoDB与MyISAM存储引擎的区别与选择

存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。 存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可被称为表类型。我们可以在创建表的时候&#xff0c;来指定选择的存储引擎&#xff0c;如果没有指定将自动选择默认的存储引擎。…

【学习笔记二十一】EWM仓库两步拣配配置及操作展示

一、EWM两步拣配配置 1.定义两步拣配的WPT ①第一步:标准WPT2020,目标仓位是2010两步拣配的仓位,并创建存储类型2010的两步拣配的仓位 ②第二步,标准WPT2010,目标仓位9020发货区和发货的仓位 2.定义确定仓库处理类型的控制标识 3.确定仓库处理类型 4.仓库编码级别需要允…

React自定义Hook函数:高效组件开发的秘密武器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C语言(扫雷游戏)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

深入了解高保真线框:设计师必备利器推荐!

什么是高保真线框 高保真线框是低保真线框的高级版本。它不仅是一个更详细的草图&#xff0c;而且是一系列经过思考的“屏幕”&#xff0c;非常接近产品的最终外观和产品的主要功能。低保真度与高保真度线框的关键区别在于&#xff1a;低保真代表设计方向和整体布局&#xff0…

模块化以及生成

导入对象 >> pip install mock >> pip install pytest-mock 下面对coverage命令参数进行简单介绍。 coverage命令共有10种参数形式&#xff0c;分别是&#xff1a; run&#xff1a;运行一个Python程序并收集运行数据&#xff1b;report&#xff1a;生成报告&#x…

@NameBinding注解名称绑定过滤器/拦截器

NameBinding注解名称绑定过滤器/拦截器&#xff0c;只针对某一些资源方法执行处理逻辑 一、为什么要用名称绑定 一般情况下&#xff0c;借助Spring的过滤器或者拦截器等对Http请求或响应进行处理就能满足需求。但是在有些场景下若只需对特定的xxxResource做拦截处理&#xff0…

数据治理实战——元数据管理

一、元数据概述 1.1 定义 描述数据的数据&#xff0c;本质还是数据。数据本身带有的技术属性与其在业务运行中的业务属性&#xff0c;称其为元数据&#xff0c;例如&#xff1a;表数据量&#xff0c;占用空间&#xff0c;字段信息&#xff0c;业务描述&#xff0c;负责人&…

Springboot+Vue项目-基于Java+MySQL的在线文档管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Gradio 流式输出教程

Gradio 流式输出教程 随着AIGC的发展&#xff0c;我逐渐发现我有许多项目&#xff0c;如果都是等待生成结束才传输出去&#xff0c;就会导致等待时间非常长&#xff0c;影响用户使用体验。在这里流式输出就显得很有必要了&#xff0c;同时也是为后续的实时处理积累一下前置条件…

​Game Maker 0.10:让创作、协作和游戏变得更简单

继去年 12 月成功发布 Game Maker 0.9 之后&#xff0c;我们又隆重推出 Game Maker 0.10。在 0.9 更新的主要增强功能基础上&#xff0c;该版本为创作者实现其愿景提供了更多改进和工具。 为此&#xff0c;The Sandbox 还正式启动了全球范围的创作者训练营&#xff0c;以帮助我…

【三维地图无人机路径规划】基于改进A星算法

课题名称&#xff1a; 基于改进A星算法的无人机三维地图路径规划 版本时间&#xff1a; 2024-04-22 程序运行&#xff1a; 直接运行AStar.m 文件即可 代码获取方式&#xff1a; QQ&#xff1a;491052175 VX&#xff1a;Matlab_Lover 改进方向&#xff1a; 预估函数增…

稀碎从零算法笔记Day56-LeetCode:组合总和 Ⅳ

题型&#xff1a;DP、数组 链接&#xff1a;377. 组合总和 Ⅳ - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给你一个由 不同 整数组成的数组 nums &#xff0c;和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的…

手撕AVL树(map和set底层结构)(1)

troop主页 今日鸡汤&#xff1a;Action may out always bring happiness;but there is no happiness without action. 行动不一定能带来快乐&#xff0c;但不行动一定不行 C之路还很长 手撕AVL树 一 AVL树概念二 模拟实现AVL树2.1 AVL节点的定义 三 插入更新平衡因子&#xff0…

mysql基础1——数据存储

mysql数据存储 共有4步 1&#xff09;创建数据库 2)确认字段 3)创建数据表 4)插入数据 1&#xff09;创建数据库 从系统架构看mysql数据库系统依次是数据库服务器&#xff0c;数据库&#xff0c;数据表和数据表的行与列 安装程序-->安装了数据库服务器 所有要做的第…

1.基于Springboot对SpringEvent初步封装

一&#xff1a;前置知识 Spring Event是Spring框架提供的一种事件机制&#xff0c;用于处理组件之间的通信。在复杂的系统中&#xff0c;模块或组件之间的通信是必不可少的。Spring Event可以用于以下场景&#xff1a; 1.系统间解耦&#xff1a;模块或组件之间通过事件进行通…