java数据结构与算法刷题-----LeetCode63. 不同路径 II

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

很多人觉得动态规划很难,但它就是固定套路而已。其实动态规划只不过是将多余的步骤,提前放到dp数组中(就是一个数组,只不过大家都叫它dp),达到空间换时间的效果。它仅仅只是一种优化思路,因此它目前的境地和线性代数一样----虚假的难。

  1. 想想线性代数,在国外留学的学生大多数不觉得线性代数难理解。但是中国的学生学习线性代数时,完全摸不着头脑,一上来就是行列式和矩阵,根本不知道这玩意是干嘛的。
  2. 线性代数从根本上是在空间上研究向量,抽象上研究线性关系的学科。人家国外的教科书都是第一讲就帮助大家理解研究向量和线性关系。
  3. 反观国内的教材,直接把行列式搞到第一章。搞的国内的学生在学习线性代数的时候,只会觉得一知半解,觉得麻烦,完全不知道这玩意学来干什么。当苦尽甘来终于理解线性代数时干什么的时候,发现人家国外的教材第一节就把这玩意讲清楚了。你只会大骂我们国内这些教材,什么狗东西(以上是自己学完线性代数后的吐槽,我们同学无一例外都这么觉得)。

而我想告诉你,动态规划和线性代数一样,我学完了才知道,它不过就是研究空间换时间,提前将固定的重复操作规划到dp数组中,而不用暴力求解,从而让效率极大提升。

  1. 但是网上教动态规划的兄弟们,你直接给一个动态方程是怎么回事?和线性代数,一上来就教行列式和矩阵一样,纯属恶心人。我差不多做了30多道动态规划题目,才理解,动态方程只是一个步骤而已,而这已经浪费我很长时间了,我每道题都一知半解不理解,过程及其痛苦。最后只能重新做。
  2. 动态规划,一定是优先考虑重复操作与dp数组之间的关系,搞清楚后,再提出动态方程。而你们前面步骤省略了不讲,一上来给个方程,不是纯属扯淡吗?
  3. 我推荐研究动态规划题目,按5个步骤,从上到下依次来分析
  1. DP数组及下标含义
  2. 递推公式
  3. dp数组初始化
  4. 数组遍历顺序(双重循环及以上时,才考虑)
  5. dp数组打印,分析思路是否正确(相当于做完题,检查一下)

在这里插入图片描述

这道题是62题的衍生题,在62题的基础上,增加了一个条件,就是路上会有障碍物,导致涉及这个障碍物的路无法通行。对应到代码就是加了一个if语句罢了。除此之外没有任何不同

可以先参考🏆LeetCode62. 不同路径https://blog.csdn.net/grd_java/article/details/135421514
先理解题目细节

在这里插入图片描述

  1. 机器人只能向右或向下走,也就是说,我们到达每一个方格,只有两种情况,从上面过来的,或者从左面过来的。注意区分“走过去”和“从哪过来的区别”,这是解出这道题的关键。
  2. 所以与其考虑到达终点有几条路可以走,不如考虑到这个位置,可以从哪里来。
  3. 要特别注意,第一行和第一列,如果到某个位置的中间有障碍物,那么就只能是0. 因为第一行和第一列,没有障碍物的情况下,也只有一条路可以到达,如果中间堵了,肯定就到不了。
解题思路
  1. 暴力求解的思想,就是回溯算法,枚举每一种情况,拿到最大值,显然会做大量无效运算。
  2. 但是如果我们预先将其存储到dp数组,就可以直接通过dp[x], 获取dp数组中指定位置x的体力花费,而不用枚举。典型的动态规划题目
动态规划思考5步曲
  1. DP数组及下标含义

我们要求出的是到达某个方块,可以从哪里过来,过来的方法有几种,那么dp数组中存储的就是到达这里有几种方法可以过来。要求出谁的可到达方法的数量呢?显然是某个方块,那么下标就是代表现在到了哪个方块,也就是代表到了某一方块后的可以过来的路。显然,需要2个下标表示,故这道题的dp数组需要二维数组

  1. 递推公式
  1. 由题意可知,只能选择向右走或者向下走,因此对于每个方块而言,只能是从上面过来,或者从左面过来。而第一行没有从上面来的路,因此只能从左面过来,也就是第一行都只有一条从左面来的路,没有障碍物的情况下都是1。同理第一列,没有从左面来的路,只能从上面过来,没有障碍物的情况下也只有从上面过来这一条路。
  1. 故:第一行和第一列没有障碍物情况下都固定为1,F(0,n) = 1; F(n,0) = 1
  2. 如果有障碍物,说明这条路不通,只能是0. 我们只需要看前一个位置通不通,就能判断当前位置通不通。F(0,n) = f(0,n-1)==0?0:1. F(n,0) = f(n-1,0)==0?0:1.
  1. 之后每一个方块,都需要考虑从上面来的路有几条,从左面来的路有几条。也就是到它上面的方块有几条路+到它左面的方块有几条路
  2. 因此,可以得到,从第二行,第二列开始,递推公式变为,到左边方块的路+到上面方块的路。F(n,n) = F(n-1,n)+F(n,n-1)
  1. dp数组初始化

在这里插入图片描述

  1. 数组遍历顺序

双重循环,我们知道这道题,数组下标表示方块的位置,也就是所在行和列的位置。那么其中一层循环代表第几行,另外一层循环代表第几列。那么先遍历行还是列呢?我们发现,无论遍历哪个,都不影响。我们可以一列一列考虑,也可以一行一行考虑,因此,先遍历哪个都一样。我们这里选择先遍历行。

  1. 打印dp数组(自己生成dp数组后,将dp数组输出看看,是否和自己预想的一样。)

在这里插入图片描述

代码:时间复杂度O(mn).空间复杂度O(mn)

在这里插入图片描述

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length, n = obstacleGrid[0].length;//获取行和列
        //dp数组代表我们站在哪个方格上,存储的元素值是,当前我们站着的方格,可以从起点走哪几条路过来,下标代表是哪个方格
        int dp[][] = new int[m][n];
        for(int i = 0 ;i<m;i++){//外循环代表 方格所在行
            for(int j = 0;j<n;j++){//内循环代表 方格所在列
                if(obstacleGrid[i][j] == 1) dp[i][j]=0;//如果当前位置是障碍物,那么我们就无法站在这个位置上,也就没有路可以到达它
                else if(i==0||j==0) {//如果是第一行,或者第一列,则最多只有一条路可以到达
                    //只有一条路,如果这条路有障碍物,必定到不了它
                    if(j>0&&dp[i][j-1]==0)dp[i][j]=0;//如果在第一行,当前位置的左边[i][j-1]位置为0,表示左边的位置就已经被障碍物堵住了路
                    else if(i>0&&dp[i-1][j]==0)dp[i][j]=0;//如果在第一列,上面位置[i-1][j] = 0, 表示上面就已经被障碍物堵住了路
                    else dp[i][j] = 1;//如果第一行或者第一列,它们那唯一的一条路,到这个位置,没有障碍物,就表示有一条路可以到达它
                }
                else{//其它位置的路为:它上面位置有几条路可以到+它左边位置有几条路可以到达它
                    dp[i][j] = dp[i-1][j]+dp[i][j-1];
                }
            }
        }
        return dp[m-1][n-1];//返回到终点,有几条路可以到达
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端鉴权拦截器实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

【GitHub】-design-pattern-extend(设计模式扩展)

写在前面 偶然间看到一篇文章 《Java 中保持扩展性的几种套路和实现》&#xff0c;写的不错&#xff0c;但是类图画的差了点儿意思。于是&#xff0c;自己动手画了画&#xff0c;对其中的内容作了一些调整&#xff0c;对包做了进一步划分&#xff0c;便于理解消化。以下是对Git…

C++ Qt开发:Charts与数据库组件联动

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍Charts组件与QSql数据库组件的常用方法及灵活…

【STM32】STM32学习笔记-定时器定时中断 定时器外部时钟(14)

00. 目录 文章目录 00. 目录01. 定时器中断相关API1.1 TIM_InternalClockConfig1.2 TIM_TimeBaseInit1.3 TIM_TimeBaseInitTypeDef1.4 TIM_ClearFlag1.5 TIM_ITConfig1.6 TIM_Cmd1.7 中断服务函数1.8 TIM_ETRClockMode2Config 02. 定时器定时中断接线图03. 定时器定时中断示例0…

嵌入式项目——平衡小车(1)

焊接 驱动板需要焊接的如上图。 陀螺仪8pin排母电机两路排线插口。(个别同学需要焊接)两个电池仓,注意电池仓分正反。 安装 底部电池板 4个 双通尼龙柱M3*224个 尼龙螺钉M3*6电机驱动板

个人笔记:分布式大数据技术原理(二)构建在 Hadoop 框架之上的 Hive 与 Impala

有了 MapReduce&#xff0c;Tez 和 Spark 之后&#xff0c;程序员发现&#xff0c;MapReduce 的程序写起来真麻烦。他们希望简化这个过程。这就好比你有了汇编语言&#xff0c;虽然你几乎什么都能干了&#xff0c;但是你还是觉得繁琐。你希望有个更高层更抽象的语言层来描述算法…

Java数组:一维数组、二维数组、Arrays

文章目录 1、一维数组1.1 数组概念1.2 数组的声明1.3 数组的静态初始化1.4 数组的动态初始化1.5 地址值1.6 数组元素访问1.7 索引1.8 数组的遍历1.9 数组两种初始化方式的区别 2、二维数组2.1 二维数组的声明2.2 二维数组的静态初始化2.3 二维数组的动态初始化2.4 二维数组的遍…

扩散模型: Diffusion Model概念讲解

Diffusion Model 课件视频前向扩散过程 在原始图像中逐步添加高斯分布随机噪声,直到最后得到完全噪声的图像。 反向降噪过程 逐步去除噪声图中的噪声,得到最后原图。 根据噪声图和时间步得到预测的噪声,然后噪声图减去噪声得到原始图 噪声预测的标签来自于前向扩散过程中添加…

TSINGSEE青犀智能分析网关V4在智慧园区车辆违停检测场景中的应用

一、背景与需求 园区作为企业办公、生产制造的重要场所&#xff0c;主要道路车辆违停等违规行为会对园区的安全造成隐患&#xff0c;并且在上下班高峰期内&#xff0c;由于发现不及时&#xff0c;车辆违停行为会造成出入口拥堵现象&#xff0c;这也成为园区管理的棘手问题。为了…

胡圆圆的暑期实习经验分享

背景 实验室一般是在研究生二年级的时候会放实习&#xff0c;在以后的日子就是自己完成毕业工作要求&#xff0c;基本上不再涉及实验室的活了&#xff0c;目前是一月份也是开始准备暑期实习的好时间。实验室每年这个时候都会有学长学姐组织暑期实习经验分享&#xff0c;本着不…

uniappVue3版本中组件生命周期和页面生命周期的详细介绍

一、什么是生命周期&#xff1f; 生命周期有多重叫法&#xff0c;有叫生命周期函数的&#xff0c;也有叫生命周期钩子的&#xff0c;还有钩子函数的&#xff0c;其实都是代表&#xff0c;在 Vue 实例创建、更新和销毁的不同阶段触发的一组钩子函数&#xff0c;这些生命周期函数…

STM32F407-14.3.10-表73具有有断路功能的互补通道OCx和OCxN的输出控制位-00x00-11x11(总结)

如上表73所示&#xff0c;主输出使能&#xff08;MOE0&#xff09;的8种OCx与OCxN的输出状态及波形图&#xff0c;已经单独整理输出8篇文章&#xff0c;方便需要时单独回查。 根据表73可得以下结论 1、从00x00~01x00的前5种状态的OCx与OCxN的引脚电平全由GPIO端口的上下拉决定…

Java序列化篇----第一篇

系列文章目录 文章目录 系列文章目录前言一、什么是java序列化,如何实现java序列化?二、保存(持久化)对象及其状态到内存或者磁盘三、序列化对象以字节数组保持-静态成员不保存四、序列化用户远程对象传输前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,…

1389 蓝桥杯 二分查找数组元素 简单

1389 蓝桥杯 二分查找数组元素 简单 //C风格解法1&#xff0c;lower_bound(),通过率100% //利用二分查找的方法在有序的数组中查找&#xff0c;左闭右开 #include <bits/stdc.h> using namespace std;int main(){int data[200];for(int i 0 ; i < 200 ; i) data[i] …

回首2023,期待2024!

2023&#xff0c;在改变中到来 2023年1月1日&#xff0c;我从成都冷清的学校回到了哈尔滨的老家&#xff0c;开始了保研之前的最后一个寒假 当时的目标是将之前的科研理论转化为实际&#xff0c;生产出一篇sci&#xff0c;助力保研加分 星移斗转&#xff0c;事与愿违&#x…

贯穿设计模式-责任链模式

样例代码 涉及到的项目样例代码均可以从https://github.com/WeiXiao-Hyy/Design-Patterns.git获取 需求 实时地&#xff0c;根据city&#xff0c;sex&#xff0c;product字段进行业务投放&#xff0c;比如&#xff1a;北京的男生&#xff1b;四川的电脑等等 → 责任链模式&…

React之useRef hook

介绍 useRef是react的自定义hook&#xff0c;它用来引用一个不需要渲染的值。这篇文章会介绍useRef的简单用法。 使用场景 1.实现节流 通过useRef实现节流功能&#xff0c;在限制时间内多次提交&#xff0c;已第一次提交为准。 useThrottle.jsx import {useEffect, useRef,…

【gRPC学习】使用go学习gRPC

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 RPC是远程调用,而google实现了grpc比较方便地实现了远程调用,gRPC是一个现代的开源远程过程调用(RPC)框架 概念介绍 在gRPC中&#xff0c;客户端应用程序可以直接调用另一台计算机上的服务器应用程序上的方法&#…

Generator - JavaScript的异步颠覆者

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》 ​ ​ 目录 ✨ 前言 什么是Generator 生成器函数的执行流程控制 异步编程应用 ✨ 结语 ✨ 前言 Java…

滑动窗口协议仿真(2024)

1.题目描述 滑动窗口协议以基于分组的数据传输协议为特征&#xff0c;该协议适用于在数据链路层以及传输层中对按 顺序传送分组的可靠性要求较高的环境。在长管道传输过程&#xff08;特别是无线环境&#xff09;中&#xff0c;相应的滑动窗口 协议可实现高效的重传恢复。附录 …