【LeetCode热题100】打卡第37天:岛屿数量反转链表

文章目录

  • 【LeetCode热题100】打卡第37天:岛屿数量&反转链表
    • ⛅前言
  • 岛屿数量
    • 🔒题目
    • 🔑题解
  • 反转链表
    • 🔒题目
    • 🔑题解

【LeetCode热题100】打卡第37天:岛屿数量&反转链表

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页💖:知识汲取者的博客

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

Github地址📁:Chinafrfq · GitHub

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

岛屿数量

🔒题目

原题链接:200.岛屿数量

image-20230714100415618

🔑题解

  • 解法一:DFS

    对于这种搜索类的题目,DFS和BFS是一个比较直接的思想

    1. 我们需要遍历每一个节点,每一个节点都有可能成为搜索的起始点
    2. 然后将每一个搜索过的点,进行标记,下一次搜索就直接跳过
    3. 我们需要遍历前后左右四点

    image-20230714130352282

    /**
     * @author ghp
     * @title
     * @description
     */
    class Solution {
        public int numIslands(char[][] grid) {
            int n = grid.length;
            int m = grid[0].length;
            int count = 0;
            boolean[][] vis = new boolean[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (!vis[i][j] && grid[i][j] != '0') {
                        // 当前节点没有遍历过,并且不是水,则进行深度搜索
                        dfs(grid, vis, i, j);
                        count++;
                    }
                }
            }
            return count;
        }
    
        private void dfs(char[][] grid, boolean[][] vis, int i, int j) {
            if (i < 0 || i > grid.length-1 || j < 0 || j > grid[0].length-1 || grid[i][j] == '0') {
                // 超出范围或遇到水,结束搜索
                return;
            }
            if (vis[i][j]){
                // 节点已遍历
                return;
            }
            // 将已遍历的节点标记为true
            vis[i][j] = true;
            // 往右遍历
            dfs(grid, vis, i, j + 1);
            // 往左遍历
            dfs(grid, vis, i, j - 1);
            // 往下遍历
            dfs(grid, vis, i + 1, j);
            // 往上遍历
            dfs(grid, vis, i - 1, j);
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm),需要遍历每一个节点
    • 空间复杂度: O ( n ∗ m ) O(n*m) O(nm),vis数组空间占用 n ∗ m n*m nm,递归调用如果全是陆地,则需要递归 n ∗ m n*m nm次,如果全是水,或者水和陆地均衡分布,只需要递归1次

    其中 n n n 为数组的行, m m m为数组的列

    代码优化:空间优化

    前面我们使用一个vis数组来记录节点是否遍历,由于我们对于每一个节点只需要遍历一遍,所以可以直接将遍历过的节点置为0,即可,所以可以直接省略掉vis数组

    class Solution {
        public int numIslands(char[][] grid) {
            int count = 0;
            for (int i = 0; i < grid.length; i++) {
                for (int j = 0; j < grid[0].length; j++) {
                    if (grid[i][j] != '0') {
                        dfs(grid, i, j);
                        count++;
                    }
                }
            }
            return count;
        }
    
        private void dfs(char[][] grid, int i, int j) {
            if (i < 0 || i > grid.length - 1 || j < 0 || j > grid[0].length - 1 || grid[i][j] == '0') {
                // 超出范围或遇到水,结束搜索
                return;
            }
            grid[i][j] = '0';
            // 往右遍历
            dfs(grid, i, j + 1);
            // 往左遍历
            dfs(grid, i, j - 1);
            // 往下遍历
            dfs(grid, i + 1, j);
            // 往上遍历
            dfs(grid, i - 1, j);
        }
    }
    
  • 解法二:BFS

    一般能用DFS的题目都可以使用BFS来解决,实现思路也比较简单,本题是一个很规范的BFS和DFS的题

    import java.util.LinkedList;
    import java.util.Queue;
    
    /**
     * @author ghp
     * @title
     * @description
     */
    class Solution {
        public int numIslands(char[][] grid) {
            int count = 0;
            for (int i = 0; i < grid.length; i++) {
                for (int j = 0; j < grid[0].length; j++) {
                    if (grid[i][j] != '0') {
                        // 不是水,则可以进行搜索
                        bfs(grid, i, j);
                        count++;
                    }
                }
            }
            return count;
        }
    
        private void bfs(char[][] grid, int i, int j) {
            // 方向数组:上、下、左、右
            int[][] direction = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
            Queue<int[]> queue = new LinkedList<>();
            // 搜索起始节点
            queue.add(new int[]{i, j});
            // 开始广度搜索
            while (!queue.isEmpty()) {
                // 回到上一个点的位置
                int[] cur = queue.poll();
                i = cur[0];
                j = cur[1];
                // 遍历四个方向
                for (int k = 0; k < 4; k++) {
                    int a = i + direction[k][0];
                    int b = j + direction[k][1];
                    if (0 <= a && a < grid.length && 0 <= b && b < grid[0].length && grid[a][b] != '0') {
                        queue.add(new int[]{a, b});
                        grid[a][b] = '0';
                    }
                }
            }
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm)
    • 空间复杂度: O ( m i n ( n , m ) ) O(min(n,m)) O(min(n,m)),即使最坏情况,整个网格都是陆地,队列的中的元素最多是 min(n,m)

    其中 n n n 为数组的行, m m m为数组的列

  • 解法三:并查集(详情看LeetCode官网)

    这题我们只需要掌握好前面两种解法即可

    class Solution {
        class UnionFind {
            int count;
            int[] parent;
            int[] rank;
    
            public UnionFind(char[][] grid) {
                count = 0;
                int m = grid.length;
                int n = grid[0].length;
                parent = new int[m * n];
                rank = new int[m * n];
                for (int i = 0; i < m; ++i) {
                    for (int j = 0; j < n; ++j) {
                        if (grid[i][j] == '1') {
                            parent[i * n + j] = i * n + j;
                            ++count;
                        }
                        rank[i * n + j] = 0;
                    }
                }
            }
    
            public int find(int i) {
                if (parent[i] != i) parent[i] = find(parent[i]);
                return parent[i];
            }
    
            public void union(int x, int y) {
                int rootx = find(x);
                int rooty = find(y);
                if (rootx != rooty) {
                    if (rank[rootx] > rank[rooty]) {
                        parent[rooty] = rootx;
                    } else if (rank[rootx] < rank[rooty]) {
                        parent[rootx] = rooty;
                    } else {
                        parent[rooty] = rootx;
                        rank[rootx] += 1;
                    }
                    --count;
                }
            }
    
            public int getCount() {
                return count;
            }
        }
    
        public int numIslands(char[][] grid) {
            if (grid == null || grid.length == 0) {
                return 0;
            }
    
            int nr = grid.length;
            int nc = grid[0].length;
            int num_islands = 0;
            UnionFind uf = new UnionFind(grid);
            for (int r = 0; r < nr; ++r) {
                for (int c = 0; c < nc; ++c) {
                    if (grid[r][c] == '1') {
                        grid[r][c] = '0';
                        if (r - 1 >= 0 && grid[r-1][c] == '1') {
                            uf.union(r * nc + c, (r-1) * nc + c);
                        }
                        if (r + 1 < nr && grid[r+1][c] == '1') {
                            uf.union(r * nc + c, (r+1) * nc + c);
                        }
                        if (c - 1 >= 0 && grid[r][c-1] == '1') {
                            uf.union(r * nc + c, r * nc + c - 1);
                        }
                        if (c + 1 < nc && grid[r][c+1] == '1') {
                            uf.union(r * nc + c, r * nc + c + 1);
                        }
                    }
                }
            }
    
            return uf.getCount();
        }
    }
    
    作者:LeetCode
    链接:https://leetcode.cn/problems/number-of-islands/solution/dao-yu-shu-liang-by-leetcode/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

反转链表

🔒题目

原题链接:206.反转链表

image-20230714131704461

🔑题解

  • 解法一:暴力

    public class Solution {
        public ListNode reverseList(ListNode head) {
            if (head == null){
                return null;
            }
            List<Integer> list = new ArrayList<>();
            while (head != null){
                list.add(head.val);
                head = head.next;
            }
            Collections.reverse(list);
            ListNode newHead = new ListNode(list.remove(0));
            ListNode p = newHead;
            while (!list.isEmpty()){
                p.next = new ListNode(list.remove(0));
                p = p.next;
            }
            return newHead;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)

    其中 n n n 为链表节点的数量

  • 解法二:双指针迭代实现

    image-20230714133700394

    public class Solution {
        public ListNode reverseList(ListNode head) {
            ListNode pre = null;
            ListNode cur = head;
            while (cur != null){
                ListNode next = cur.next;
                cur.next = pre;
                pre = cur;
                cur = next;
            }
            return pre;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    其中 n n n 为数组中元素的个数

  • 解法三:双指针递归实现

    image-20230714135134246

    public class Solution {
        public ListNode reverseList(ListNode head) {
            if (head == null || head.next == null){
                return head;
            }
            ListNode newHead = reverseList(head.next);
            head.next.next = head;
            head.next = null;
            return newHead;
        }
    }
    

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

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

相关文章

【Spring core学习二】创建Spring 项目 Spring的存

目录 &#x1f31f;一、创建最原始的Spring-core项目。 &#x1f31f;二、怎么往Spring中存取对象&#xff1f; &#x1f337;1、在Spring中存对象 &#x1f337;2、通过getBean获取对象的三种方式 &#x1f337;3、通过factory方式获取对象 &#x1f31f;三、对存对象的…

用github的copilot;tmux中进去了> 怎么退出

1、首先要学籍认证 &#xff08;前提&#xff1a;(241条消息) Copilot使用的关卡——GitHub教育认证方法和注意事项_github教师认证_石去皿的博客-CSDN博客&#xff09; 网址&#xff1a;Are you a student? - GitHub Education (241条消息) GitHub学生认证&#xff0c;可…

微信小程序开发学习之页面导航(声明式导航和编程式导航)

微信小程序之页面导航&#xff08;声明式导航和编程式导航&#xff09; 1.0 页面导航1.1. 声明式导航1.1.1. 导航到tabBar页面1.1.2. 导航到非tabBar页面1.1.3. 后退导航 1.2. 编程式导航1.2.1. 导航到tabBar页面1.2.2. 导航到非tabBar页面1.2.3. 后退导航 1.3. 导航传参1.3.1.…

开发工具篇第25讲:阿里云MFA绑定Chrome浏览器Authenticator插件

开发工具篇第25讲&#xff1a;阿里云MFA绑定Chrome浏览器Authenticator插件 本文是开发工具篇第25讲&#xff0c;登录阿里云旗下产品时&#xff0c;需要使用mfa登录&#xff0c;每次如果要用手机看mfa码很麻烦&#xff0c; Chrome浏览器提供了一个快捷的登录方法&#xff0c;可…

Mac上提取应用APP的LOGO

1、找到想提取LOGO的应用&#xff0c;右键「显示包内容」 2、 双击【Contents】文件夹&#xff0c;再双击【Resources】文件夹 3、双击图标打开&#xff0c;选择最清晰的一帧&#xff0c;右键【导出为】 4、选择保存位置&#xff0c;格式注意选择常见格式&#xff0c;如png

通过git管理远程gitee仓库(push、pull)

通过git管理远程gitee仓库&#xff08;push、pull&#xff09; Git:是一种分布式版本控制系统&#xff0c;用于跟踪和管理软件开发项目的源代码和文件。它可以记录文件的修改历史&#xff0c;允许多人协同工作&#xff0c;并提供了撤销更改、分支管理、合并代码等功能。 Git最初…

一、对象的概念(2)

本章概要 复用继承 “是一个”与“像是一个”的关系 多态 复用 一个类经创建和测试后&#xff0c;理应是可复用的。然而很多时候&#xff0c;由于程序员没有足够的编程经验和远见&#xff0c;我们的代码复用性并不强。 代码和设计方案的复用性是面向对象程序设计的优点之一…

Spring Boot 中的 @Query 注解是什么,原理,如何使用

Spring Boot 中的 Query 注解是什么&#xff0c;原理&#xff0c;如何使用 在 Spring Boot 中&#xff0c;Query 注解是一个非常常用的注解&#xff0c;用于定义自定义查询语句。本文将介绍 Query 注解的作用、原理和使用方法。 1. Query 注解的作用 在 Spring Boot 中&#…

Linux——进程信号的发送

目录 一.信号发送的概念 首先来讲几个发送术语&#xff1a; 它有三种情况&#xff1a; 注意&#xff1a; 二.信号在内核中的表示示意图 三.信号捕捉 所以总结一下&#xff1a; 此时&#xff0c;会出现这样一个疑问&#xff1a;操作系统是如何得知现在被执行的进程是用户态…

【Spring Cloud Alibaba Seata 处理分布式事务】——每天一点小知识

&#x1f4a7; S p r i n g C l o u d A l i b a b a S e a t a 处理分布式事务 \color{#FF1493}{Spring Cloud Alibaba Seata 处理分布式事务} SpringCloudAlibabaSeata处理分布式事务&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f98…

SpringCloud(4) Eureka 如何主动下线服务节点

目录 1.直接停掉客户端服务2.发送HTTP请求1&#xff09;调用DELETE接口2&#xff09;调用状态变更接口 3.客户端主动通知注册中心下线1&#xff09;代码示例2&#xff09;补充3&#xff09;测试 一共有三种从 Eureka 注册中心剔除服务的方式&#xff1a; 1.直接停掉客户端服务…

Unity Obfuscator

官方仓库 学习日期&#xff1a;2023-07-13&#xff08;防止后续仓库特性或功能更新无对比时间&#xff09; 目标&#xff1a;本文介绍使用此github库&#xff0c;混淆unity项目的代码&#xff0c;在ILSpy中无法正确反编译。 一、说明 官方说明 配置界面 Features: ControlFlow…

【Spring Boot】单元测试

单元测试 单元测试在日常项目开发中必不可少&#xff0c;Spring Boot提供了完善的单元测试框架和工具用于测试开发的应用。接下来介绍Spring Boot为单元测试提供了哪些支持&#xff0c;以及如何在Spring Boot项目中进行单元测试。 1.Spring Boot集成单元测试 单元测试主要用…

LabVIEW FPGA利用响应式数字电子板快速开发空间应用程序

LabVIEW FPGA利用响应式数字电子板快速开发空间应用程序 与传统的基于文本的语言相比&#xff0c;LabVIEW的编程和设计已被证明可以缩短开发时间。各种研究表明&#xff0c;生产率的提高在3到10倍之间。LabVIEW通过图形语言、集成开发环境和多个编译器的组合来实现这一点。 图…

Django_发送邮件

目录 一、开启SMTP服务并获取授权码 二、在Django的配置文件中添加邮箱服务配置 三、发送邮箱代码 源码等资料获取方法 使用django邮箱功能需要搭建smtp服务器&#xff0c;如果没有&#xff0c;可以使用第三方smtp服务器。 本文以第三方QQ邮箱服务器演示如何使用python的s…

接口的幂等性如何设计

前言 所谓幂等: 多次调用方法或者接口不会改变业务状态&#xff0c;可以保证重复调用的结果和单次调用的结果一致。 我们在开发中主要操作也就是CURD,其中读取操作和删除操作是天然幂等的&#xff0c;我们所关心的就是创建操作、更新操作。 创建操作一定是非幂等的因为要涉及…

SpringBoot 如何使用 MockMvc 进行 Web 集成测试

SpringBoot 如何使用 MockMvc 进行 Web 集成测试 介绍 SpringBoot 是一个流行的 Java Web 开发框架&#xff0c;它提供了一些强大的工具和库&#xff0c;使得开发 Web 应用程序变得更加容易。其中之一是 MockMvc&#xff0c;它提供了一种测试 SpringBoot Web 应用程序的方式&…

(EMQX)STM32L+BC20+MQTT协议传输温湿度,ADC,电压,GPS数据到EMQX

1、材料准备 准备以下材料 2、设备连接 2.1 插入物联网卡&#xff0c;天线 首先把BC20核心板从开发板上拆下来 然后将物联卡放置在BC20核心板内 物联卡放置完成将BC20核心板重新插入到开发板内&#xff08;注意不要弄错方向&#xff09; 同时接入天线 2.2 连接ST-Link仿真…

RabbitMQ系列(27)--RabbitMQ使用Federation Exchange(联邦交换机)解决异地访问延迟问题

前言&#xff1a; (broker北京)、(broker深圳)彼此之间相距甚远&#xff0c;网络延迟是一个不得不面对的问题。有一个在北京的业务(Client北京&#xff09;需要连接(broker北京),向其中的交换器exchangeA发送消息&#xff0c;此时的网络延迟很小,(Client北京)可以迅速将消息发…

嵌入式QT- QT使用MQTT

目录 一、MQTT介绍 二、MQTT概念 2.1 订阅(Subscribtion) 2.2 会话&#xff08;Session&#xff09; 2.3 主题名&#xff08;Topic Name&#xff09; 2.4 主题筛选器&#xff08;Topic Filter&#xff09; 2.5 消息订阅 三、MQTT中的角色 3.1 客户端 3.2 服务器 四、X86平…