LeetCode-hot100题解—Day6

原题链接:力扣热题-HOT100
我把刷题的顺序调整了一下,所以可以根据题号进行参考,题号和力扣上时对应的,那么接下来就开始刷题之旅吧~
1-8题见LeetCode-hot100题解—Day1
9-16题见LeetCode-hot100题解—Day2
17-24题见LeetCode-hot100题解—Day3
25-34题见LeetCode-hot100题解—Day4
39-56题见LeetCode-hot100题解—Day5
注:需要补充的是,如果对于每题的思路不是很理解,可以点击链接查看视频讲解,是我在B站发现的一个宝藏UP主,视频讲解很清晰(UP主用的是C++),可以结合视频参考本文的java代码。

力扣hot100题解 62-71

    • 62.不同路径
    • 63.不同路径Ⅱ
    • 64.最小路径和
    • 66.加一
    • 67.二进制求和
    • 69.x的平方根
    • 70.爬楼梯
    • 71.简化路径

62.不同路径

思路
本题采用动态规划来求解,最后需要得到的时候到达网格右下角的路径的数量,设f(i,j)是到达f[i][j]的路径数量,由于每次只能向下或者向右移动,所以可以用f(i,j)=f(i-1,j)+f(i,j-1)来计算路径数量,其中f(i-1,j)是指到f[i][j]上一格的数量,f(i,j-1)是指到达f[i][j]左边一格的路径数量,那么动态方程为f(i,j)=f(i-1,j)+f(i,j-1),最后返回f(m-1,n-1)的值即为所求,详细的视频讲解点击视频讲解-不同路径。
时间复杂度
由于要对整个二维数组进行遍历计算,所以时间复杂度为O(mn),需要开辟一个二维数组来存储对应格子的路径数,所以空间复杂度也为O(mn)
代码实现

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] f = new int[m][n];
        for(int[] item : f){
            Arrays.fill(item,1);
        }
        for(int i = 1; i < m; i++){
            for(int j = 1;j < n;j++){
                f[i][j] = f[i - 1][j] + f[i][j - 1];
            }
        }
        return f[m-1][n-1];
    }
}

知识点扩展
对数组元素进行初始化设置可以使用以下函数,需要注意的是是的,Arrays.fill(nums,x)方法只能用于一维数组。该方法用指定的值填充整个数组,对于多维数组,每个维度需要分别使用fill方法进行填充。

//将nums数组的元素初始化为x
Arrays.fill(nums,x)

63.不同路径Ⅱ

思路
本题是62题的加强版,思路基本一样,都用到了动态规划的方法,唯一不同的是本题中多了一个障碍物的限制,有障碍物的网格是不能经过的,所以我们只要加一个判断条件,如果某个网格有障碍物,则将这个网格的可到达路径设置为0即可,需要注意的是本题不能将记录路径数的二维数组初始化值为1,而应该是0,62题中第一行(i=0)和第一列(j=0)因为只能向右和向下走才能到达,所以将其初始值设置为1,在后续的遍历中就可以直接从i=1j=1开始遍历数组,但是本题中第一行和第一列可能会出现障碍物,所以也要统一处理,遍历时也需要从0开始,同时为了保证第一行和第一列没有障碍物时可能正确的记录其可到达的路径数量,需要将其实位置的路径数置为1,视频讲解点击视频讲解-不同路径Ⅱ。
时间复杂度
时间复杂度和空间复杂度同62题,均为O(mn)
代码实现

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] f = new int[m][n];
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                //判断是否有障碍物,有则直接跳过
                if(obstacleGrid[i][j] == 1) continue;
                //将f[0][0] = 1,方便对第一行和第一列的路径数的计算
                if(i == 0 && j == 0) f[i][j] = 1;
                else{
                    //i>0时 路径数等于到达上面格子的路径数+f[i][j]
                    if(i > 0) f[i][j] += f[i - 1][j];
                    //j>0时 路径数等于到达左边格子的路径数+f[i][j]
                    if(j > 0) f[i][j] += f[i][j - 1];
                }
            }
        }
        return f[m - 1][n - 1];
    }
}

64.最小路径和

思路
本题采用动态规划的方法来解决,设f(i,j)表示从(0,0)到(i,j)的路径和,由于每次只能向右或者向下走,所以可以得到以下的两个动态方程:

//从上面格子向下走
f[i][j] = f[i - 1][j] + grid[i][j]
//从左边格子向右走
f[i][j] = f[i][j - 1] + grid[i][j]

要得到最小路径和,所以两种走法中取最小值即可,所以最终的动态方程为:

f[i][j] = Math.min(f[i - 1][j],f[i][j - 1]) + grid[i][j]

注意最后在代码中不要直接使用该动态方程,因为要分别处理ij为0的情况,视频讲解点击视频讲解-最小路径和。
时间复杂度
由于要遍历二维数组得到每一格的路径和,所以时间复杂度为O(mn),开辟一个二维数组来记录每一格的路径和,所以空间复杂度为O(mn)
代码实现

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] f = new int[m][n];
        //初始化为最大值
        for(int[] item : f){
            Arrays.fill(item,Integer.MAX_VALUE);
        }

        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                //(0,0)处的值为网格的值,特判处理
                if(i == 0 && j == 0) f[i][j] = grid[i][j];
                else{
                    //处理j为0,即第一列的情况
                    if(i > 0) f[i][j] = Math.min(f[i][j],f[i - 1][j] + grid[i][j]);
                    //处理i为0,即第一行的情况
                    if(j > 0) f[i][j] = Math.min(f[i][j],f[i][j - 1] + grid[i][j]);
                }
            }
        }
        return f[m - 1][n - 1];
    }
}

66.加一

思路
本题需要对数组元素组成的数字进行加一操作,重点在于加法操作中对进位的处理,可以分为两种情形:

  • 当数组最后一个元素小于9时,最后一个元素直接加一,然后直接返回数组即可。
  • 当数组最后一个元素大于9时,需要考虑到进位,将数组最后一个元素置为0,进位+1,然后继续对倒数第二个元素进行加一处理,依次类推。这里需要对数组元素全是9做特判处理,需要在结果数组的开头插入元素1。

视频讲解点击视频讲解-加一。
时间复杂度
这个算法的时间复杂度为O(n),其中n是输入数组digits的长度。在大多数情况下,算法只需遍历一次数组,因此时间复杂度为O(n)。但在最坏情况下,需要创建一个新的数组,并将所有元素复制到新数组中,此时时间复杂度为O(n+1),即O(n)。因此,可以将算法的时间复杂度简化为O(n)
代码实现

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i = digits.length - 1 ;i >= 0; i--){
            if(digits[i] < 9){
                digits[i]++;
                break;
            }else{
                digits[i] = 0;
                if(i == 0){
                    int[] newdigits = new int[digits.length + 1];
                    newdigits[0] = 1;
                    for(int j = 1; j < digits.length + 1 ;j++){
                        newdigits[j] = digits[j - 1];
                    }
                    digits = newdigits;
                }
            }
        }
        return digits;
    }
}

67.二进制求和

思路
本题直接对二进制进行求和,使用StringBuilder来构建结果字符串(关于StringBuilder的使用下面的知识拓展中做了总结,之前系列文章中也有简单介绍(LeetCode-hot100题解—Day3中 17.电话号码的字母组合),因为要动态的往结果数组里添加元素,所以不建议直接使用String),并使用carry变量来记录进位。从字符串的末尾开始,逐位相加,并将结果插入到StringBuilder的开头。代码中将ab两个字符串中对应位置的元素全部加到carry中,最后使用carry%2得到结果,carry/2更新carry的值。视频讲解点击视频讲解-二进制求和,其中有详细的模拟演示。
时间复杂度
该方法的时间复杂度为O(max(n,m)),其中分别是字符串ab的长度。在最坏情况下,需要遍历较长的字符串并执行常数时间操作。所以时间复杂度可以看成O(n)
代码实现

class Solution {
    public String addBinary(String a, String b) {
        StringBuilder ans = new StringBuilder();
        int carry = 0;
        int i = a.length() - 1;
        int j = b.length() - 1;
        while(i >= 0 || j >= 0 || carry > 0){
            if(i >= 0){
                carry += a.charAt(i) - '0';
                i--;
            } 
            if(j >= 0){
                carry += b.charAt(j) - '0';
                j--;
            }        
            ans.insert(0,carry % 2);
            carry /= 2;
        }
        return ans.toString();
    }
}

知识拓展
以下总结了StringBuilder的一些基本用法,需要注意的是,StringBuilder是线程不安全的,如果需要在多线程环境中使用,应该考虑使用StringBuffer类。

//1.创建StringBuilder对象
//创建一个空的StringBuilder对象
StringBuilder s = new StringBuilder();
//创建一个包含初始字符串的StringBuilder对象
StringBuilder s = new StringBuilder("Hello");
//创建一个初始容量为100的StringBuilder对象
StringBuilder s = new StringBuilder(100);

//2.添加字符串或字符
//添加字符串
s.append("World")
//添加空字符串
s.append(" ");
//添加一个字符
s.append('!');

//3.插入字符串或字符
//在索引5处插入字符串"world"
s.insert(5,"world");
//在索引0处插入字符'!'
s.insert(0,'!');

//4.删除字符或字符串
//删除索引5到10之间的字符,包括索引为5的字符,不包括索引为10的字符,左闭右开
s.delete(5,10);
//删除索引0处的字符
s.deleteCharAt(0);

//5.替换字符串或字符
//替换索引5到10之间的字符为"nihao"
s.replace(5,10,"nihao");
//替换索引0处的字符为"N"
s.replace(0,1,"N");

//6.获取字符串
//将StringBuilder对象转换为字符串
String str = s.toString();

69.x的平方根

思考
由于题目不允许使用任何内置指数函数和算符,所以采用二分查找来解决该问题。首先定义左右边界,计算中点mid的平方值,如果该值小于等于x值,则说明x的平方根在mid的右侧,此时更新左边界l的值为mid(因为mid的值也可能是结果);如果该值大于x,则说明x的平方根在mid的左侧,此时更是右边界r的值为mid-1mid的平方值大于x,所以mid肯定不是所求的结果),最后循环结束,返回l和r任意一个即为所求,视频讲解点击视频讲解-x的平方根。
时间复杂度
使用二分查找,时间复杂度为O(logn)
代码实现

class Solution {
    public int mySqrt(int x) {
        int l = 0;
        int r = x;
        while(l < r){
            int mid = l + (r - l) / 2 + 1;
            if((long)mid * mid <= x) l = mid;
            else r = mid - 1; 
        }
        return l;
    }
}

70.爬楼梯

思路:
本题采用动态规划来解决,假设f(i)表示爬到i阶的方法数,那么f(1) = 1,第1阶爬1阶到达,有一种方法,f(2)=2,第2阶可以可以从1阶爬到2阶,也可以直接爬2阶到2,所以有两种方法;由于一次可以爬1阶或2阶,所以动态方程为f(i)=f(i-1)+f(i-2),其中f(i-1)表示爬到i-1阶的方法数,爬到i需要爬1阶,可以到达i阶,f(i-2)表示爬到i-2阶的方法数,爬到i阶需要爬2阶,可以到达i阶,两者加起来即为爬到i阶的方法数,视频讲解点击视频讲解-爬楼梯。
时间复杂度
时间复杂度为O(n),由于开辟了一个数组来保存爬到每一阶的方法数,空间复杂度为O(n)
代码实现

class Solution {
    public int climbStairs(int n) {
        //数组大小设置为n+2,防止溢出
        int[] f = new int[n + 2];
        f[1] = 1;
        f[2] = 2;
        for(int i = 3;i <= n;i++){
            f[i] = f[i - 1] + f[i - 2];
        }
        return f[n];
    }
}

71.简化路径

思路
根据题意可知,当在路径中遇到"."时表明当前目录,不做处理;当在路径中遇到".."时表明上级目录,需要返回上级目录,所以可以将path中的目录全部压入栈中,当遇到".."时,弹出栈顶元素(即回到上一级目录),最后在遍历完path后将栈中的元素逆序拼接输出即可,如果栈为空,直接返回根目录"/",视频讲解点击视频讲解-简化路径。关于javaStack的使用在之前系列文章(LeetCode-hot100题解—Day3 20.有效的括号)中总结过,如果需要可以去复习一下。
时间复杂度
时间复杂度是O(n),其中n是路径字符串path的长度,只对path进行了一次遍历。
代码实现

class Solution {
    public String simplifyPath(String path) {
        Stack<String> stk = new Stack<>();
        String[] items = path.split("/");
        for(String item : items){
            if(item.equals("..")){
                if(!stk.isEmpty()){
                    stk.pop();
                }
            }else if(!item.equals(".") && !item.equals("")){
                stk.push(item);
            }
        }
        StringBuilder ans = new StringBuilder();
        while(!stk.isEmpty()){
            ans.insert(0,"/"+stk.pop());
        }
        //如果栈为空,直接返回根目录"/"
         return ans.length() == 0 ? "/" : ans.toString();
    }
}

知识拓展
equals==的使用
使用"=="运算符判断两个对象是否相等时,它实际上比较的是两个对象的引用地址,而不是它们的值,也就是说,它检查的是两个对象是否指向相同的内存位置。
而使用equals()方法可以比较两个对象的值是否相等,equals() 不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。在Java中,equals()方法是Object类的方法,所有的类都继承了它。默认情况下,equals()方法与"=="运算符的行为相同,比较的是两个对象的引用地址。
但是,很多类会覆盖equals()方法,以便根据对象的内容来判断它们是否相等。例如,在字符串类(String)中,String 中的 equals 方法是被重写过的,equals()方法比较的是字符串的内容(也就是对象的值),而不是引用地址。
因此,如果你想比较两个对象的值是否相等,应该使用equals()方法,而不是"=="运算符。

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

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

相关文章

Windows下安装人大金仓数据库

1、点击安装包进行安装 2、双击进行安装 3、点击确定 4、接着选择下一步 5、勾选接收 6、选择授权文件 7、显示授权文件信息 8、选择安装位置 9、点击安装 10、点击下一步 11、正在进行安装 12、设置密码。123456 13、系统正在进行配置 14、安装完成 15、登…

17 【Aseprite 作图】参考图和颜色

参考图 Aseprite 作图&#xff0c;“打开 - 一张参考图”&#xff0c;再把参考图拉到右边&#xff0c;就可以得到参考图和缩略图 取消选区 通过“选择 - 取消选择”&#xff0c;可以 取消选区 复制参考图的颜色 打开参考图后&#xff0c;参考图的调色板就会出现参考图所有的…

【智能优化算法】白鲨智能优化算法(White Shark Optimizer,WSO)

白鲨智能优化算法(White Shark Optimizer,WSO)是期刊“KNOWLEDGE-BASED SYSTEMS”&#xff08;中科院一区期刊 IF8.6&#xff09;的2022年智能优化算法 01.引言 白鲨智能优化算法(White Shark Optimizer,WSO)的核心理念和基础灵感来自大白鲨的行为&#xff0c;包括它们在导航和…

Freepik图形资源网收购AI图像放大工具Magnific:图像放大技术的融合与创新

近日&#xff0c;全球最大的高质量图形资源网站Freepik宣布收购领先的AI图像放大工具Magnific&#xff0c;这一举措标志着Freepik在图像处理技术领域的重大突破与扩张。Magnific以其独特的高分辨率放大、细节重构与增强、创意滑块调整等功能&#xff0c;赢得了广泛的市场认可和…

vivado新版本兼容老版本,vitis classic兼容sdk教程

new version: vivado版本2023.2 和vitisv classic 2023.2 old version: vivado 2018.3以及之前的版本 打开工程 自动升级到当前版本&#xff0c;选择OK 点击Yes,合并当前的目录架构 点击OK 点击Report IP status 勾选要升级的IP核&#xff0c;点击升级 在项目工程文件夹…

如何编译不同目录下的两个文件

1.直接编译 2.打包成动静态库进行链接

【Redis】RDB持久化和AOF 持久化

分布式缓存 单点 Redis 的问题 数据丢失&#xff08;持久化&#xff09;并发能力不如集群&#xff08;主从集群、读写分离&#xff09;Redis宕机导致服务不可用&#xff08;Redis哨兵&#xff09;存储能力差&#xff08;分片集群&#xff09; Redis 持久化 RDB 持久化 什么…

vue3对象数组格式的动态表单校验

如你有一个表单&#xff0c;表单内容是对象&#xff0c;但是对象内还有可动态循环的数组进行动态表单校验。 效果如图&#xff1a;查看源码 页面内容&#xff1a; <div class"arrForm-Box"><el-form :model"state.formData" :rules"rule…

第十一篇:操作系统新纪元:智能融合、量子跃迁与虚拟现实的交响曲

操作系统新纪元&#xff1a;智能融合、量子跃迁与虚拟现实的交响曲 1 引言 在数字化的浪潮中&#xff0c;操作系统如同一位智慧的舵手&#xff0c;引领着信息技术的航船穿越波涛汹涌的海洋。随着人工智能、物联网、量子计算等前沿技术的蓬勃发展&#xff0c;操作系统正站在一个…

【HMWeb】HTML使用Leaflet实现本地离线地图Gis应用

下载Leaflet 官网下载&#xff1a;https://leafletjs.com/reference.html CSDN&#xff1a;https://download.csdn.net/download/hmxm6/89291989 选择版本号 添加html文件 加入代码 <!DOCTYPE html> <html lang"en"> <head><meta charset&qu…

Transformers中加载预训练模型的过程剖析

使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记…

设置LCD为第二终端

我一直使用xshell端&#xff0c;开发板通过串口和 xshell进行通信。 调试好LCD 驱动之后&#xff0c;可以设置 LCD 作为终端&#xff0c;也就是开发板使用自己的显示 设备作为自己的终端&#xff0c;然后接上键盘就可以直接在开发板上敲命令了&#xff0c;将 LCD 设置为终端控制…

服务器内存占用不足会怎么样,解决方案

在当今数据驱动的时代&#xff0c;服务器对于我们的工作和生活起着举足轻重的作用。而在众多影响服务器性能的关键因素当中&#xff0c;内存扮演着极其重要的角色。 服务器内存&#xff0c;也称RAM&#xff08;Random Access Memory&#xff09;&#xff0c;是服务器核心硬件部…

ETL免费工具kettle(PDI),安装和配置

起源&#xff1a; Kettle最早是一个开源的ETL工具&#xff0c;全称为KDE Extraction, Transportation, Transformation and Loading Environment。在2006年&#xff0c;Pentaho公司收购了Kettle项目&#xff0c;原Kettle项目发起人Matt Casters加入了Pentaho团队&#xff0c;成…

鲁教版六年级数学上册-笔记

文章目录 第一章 丰富的图形世界1 生活中的立体图形2 展开和折叠3 截一个几何体4 从三个方向看物体的形状 第二章 有理数及其运算1 有理数2 数轴3 绝对值4 有理数的加法5 有理数的减法6 有理数的加减混合运算7 有理数的乘法8 有理数的除法9 有理数的乘方10 科学计数法11 有理数…

智慧公厕,运用数据提升公共厕所管理水平!

随着城市人口的增加和生活水平的提高&#xff0c;公共厕所的管理变得越来越重要。传统的厕所管理方式已经无法满足人们对卫生、便利和舒适的需求。而智慧公厕作为新一代公厕管理方式&#xff0c;通过运用数据技术和大数据分析手段&#xff0c;彻底改变了公厕管理的模式&#xf…

数据结构学习/复习12

一、排序概念与应用 二、插入排序 三、希尔排序 当间隔数为1时则为插入排序 1.一组一组排 2.多组并排 3.间隔数变化直至为1 四、性能测速代码

【Linux】18. 进程间通信 --- System V IPC(选学)

System V IPC System V 消息队列System V 共享内存System V 信号量 system V 共享内存 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核。 换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据…

(九)JSP教程——pageContext对象

pageContext对象是由JSP容器创建并初始化的&#xff0c;相当于当前页面的容器&#xff0c;它可以访问当前页面中的所有对象。它的主要作用是为JSP页面包装上下文&#xff0c;并用于管理属于JSP的特殊可见部分中已命名对象的访问。 一般情况下&#xff0c;使用该对象的应用并不多…

自动驾驶主流芯片及平台架构(三)低算力平台

前面有提到&#xff0c;自动驾驶等级每增加一级&#xff0c;所需要的芯片算力就会呈现十数倍的上升&#xff0c;L2级自动驾驶的算力需求仅要求2-2.5TOPS&#xff0c;但是L3级自动驾驶算力需求就需要20-30TOPS,到L4级需要200TOPS以上&#xff0c;L5级别算力需求则超过2000TOPS。…
最新文章