想要精通算法和SQL的成长之路 - 岛屿数量和岛屿的最大面积

news2024/10/7 20:37:10

想要精通算法和SQL的成长之路 - 岛屿数量和岛屿的最大面积

  • 前言
  • 一. 岛屿数量
    • 1.1 并查集数据结构构造
    • 1.2 使用并查集编码
  • 二. 岛屿的最大面积

前言

想要精通算法和SQL的成长之路 - 系列导航
并查集的运用

一. 岛屿数量

原题链接

在这里插入图片描述

从这个题目的特性来看,它适合用并查集来解决。对并查集还不清楚的,可以看下前言里面的链接。

1.1 并查集数据结构构造

这里的难点就是:

  • 如何将二维数组转化为一维数组。假设二维数组下标(i,j),长len1,高len2.
  • 那么二维下标转化为一维坐标就是:i*len2 + j
class UnionFind {
    private int[] parent;
    private int[] rank;
    private int sum;

    public UnionFind(char[][] grid) {
        // 初始化岛屿数量为0,因为我们还没有遍历数组,不知道岛屿的数量
        sum = 0;
        int len1 = grid.length;
        int len2 = grid[0].length;
        parent = new int[len1 * len2];
        rank = new int[len1 * len2];
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                // 根节点指向自己
                parent[i * len2 + j] = i * len2 + j;
                // 如果这个地方是岛屿,那么该元素对应的集合内元素数量为1
                if (grid[i][j] == '1') {
                    rank[i * len2 + j] = 1;
                    // 岛屿数量+1
                    sum++;
                }
            }
        }
    }

    public int find(int x) {
        while (x != parent[x]) {
            x = parent[x];
        }
        return x;
    }

    public void union(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX == rootY) {
            return;
        }
        // 如果根节点 rootX 的深度 > rootY。
        if (rank[rootX] > rank[rootY]) {
            // 那么将以rootY作为根节点的集合加入到rootX对应的集合当中
            rank[rootX] += rank[rootY];
            // 同时改变rootY的根节点,指向rootX。
            parent[rootY] = rootX;
        } else {
            // 反之
            rank[rootY] += rank[rootX];
            parent[rootX] = rootY;
        }
        // 岛屿数量-1
        sum--;
    }
}

1.2 使用并查集编码

public int numIslands(char[][] grid) {
    int len1 = grid.length;
    int len2 = grid[0].length;
    UnionFind unionFind = new UnionFind(grid);
    for (int i = 0; i < len1; i++) {
        for (int j = 0; j < len2; j++) {
            // 如果当前是岛屿
            if (grid[i][j] == '1') {
                // 先将当前的岛屿标识改变,避免被重复访问
                grid[i][j] = '0';
                // 分别朝4个方向,上下左右访问,如果是岛屿,开始合并
                if (i - 1 >= 0 && grid[i - 1][j] == '1') {
                    unionFind.union(i * len2 + j, (i - 1) * len2 + j);
                }
                if (i + 1 < len1 && grid[i + 1][j] == '1') {
                    unionFind.union(i * len2 + j, (i + 1) * len2 + j);
                }
                if (j - 1 >= 0 && grid[i][j - 1] == '1') {
                    unionFind.union(i * len2 + j, i * len2 + j - 1);
                }
                if (j + 1 < len2 && grid[i][j + 1] == '1') {
                    unionFind.union(i * len2 + j, i * len2 + j + 1);
                }
            }
        }
    }
    // 最后返回岛屿的数量
    return unionFind.sum;
}

最终完整代码如下:

public class Test200 {
    public int numIslands(char[][] grid) {
        int len1 = grid.length;
        int len2 = grid[0].length;
        UnionFind unionFind = new UnionFind(grid);
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                // 如果当前是岛屿
                if (grid[i][j] == '1') {
                    // 先将当前的岛屿标识改变,避免被重复访问
                    grid[i][j] = '0';
                    // 分别朝4个方向,上下左右访问,如果是岛屿,开始合并
                    if (i - 1 >= 0 && grid[i - 1][j] == '1') {
                        unionFind.union(i * len2 + j, (i - 1) * len2 + j);
                    }
                    if (i + 1 < len1 && grid[i + 1][j] == '1') {
                        unionFind.union(i * len2 + j, (i + 1) * len2 + j);
                    }
                    if (j - 1 >= 0 && grid[i][j - 1] == '1') {
                        unionFind.union(i * len2 + j, i * len2 + j - 1);
                    }
                    if (j + 1 < len2 && grid[i][j + 1] == '1') {
                        unionFind.union(i * len2 + j, i * len2 + j + 1);
                    }
                }
            }
        }
        // 最后返回岛屿的数量
        return unionFind.sum;
    }

    class UnionFind {
        private int[] parent;
        private int[] rank;
        private int sum;

        public UnionFind(char[][] grid) {
            // 初始化岛屿数量为0,因为我们还没有遍历数组,不知道岛屿的数量
            sum = 0;
            int len1 = grid.length;
            int len2 = grid[0].length;
            parent = new int[len1 * len2];
            rank = new int[len1 * len2];
            for (int i = 0; i < len1; i++) {
                for (int j = 0; j < len2; j++) {
                    // 根节点指向自己
                    parent[i * len2 + j] = i * len2 + j;
                    // 如果这个地方是岛屿,那么该元素对应的集合内元素数量为1
                    if (grid[i][j] == '1') {
                        rank[i * len2 + j] = 1;
                        // 岛屿数量+1
                        sum++;
                    }
                }
            }
        }

        public int find(int x) {
            while (x != parent[x]) {
                x = parent[x];
            }
            return x;
        }

        public void union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY) {
                return;
            }
            // 如果根节点 rootX 的深度 > rootY。
            if (rank[rootX] > rank[rootY]) {
                // 那么将以rootY作为根节点的集合加入到rootX对应的集合当中
                rank[rootX] += rank[rootY];
                // 同时改变rootY的根节点,指向rootX。
                parent[rootY] = rootX;
            } else {
                // 反之
                rank[rootY] += rank[rootX];
                parent[rootX] = rootY;
            }
            // 岛屿数量-1
            sum--;
        }
    }
}

二. 岛屿的最大面积

原题链接

在这里插入图片描述
在这里插入图片描述

这个题目就是在第一题的基础上,查找最大的集合深度,即rank的最大值。我们只需要在第一题的基础上,增加一个循环判断即可:

int maxArea = 0;
for (int i = 0; i < len1 * len2; i++) {
    maxArea = Math.max(maxArea, unionFind.rank[i]);
}
return maxArea;

注意:

  • 本题是int类型的数组,你可以全局替换一下字符:将 ' 替换成 char 替换成int

最终完整代码如下:

public class Test695 {
    public int maxAreaOfIsland(int[][] grid) {
        int len1 = grid.length;
        int len2 = grid[0].length;
        UnionFind unionFind = new UnionFind(grid);
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                // 如果当前是岛屿
                if (grid[i][j] == 1) {
                    // 先将当前的岛屿标识改变,避免被重复访问
                    grid[i][j] = 0;
                    // 分别朝4个方向,上下左右访问,如果是岛屿,开始合并
                    if (i - 1 >= 0 && grid[i - 1][j] == 1) {
                        unionFind.union(i * len2 + j, (i - 1) * len2 + j);
                    }
                    if (i + 1 < len1 && grid[i + 1][j] == 1) {
                        unionFind.union(i * len2 + j, (i + 1) * len2 + j);
                    }
                    if (j - 1 >= 0 && grid[i][j - 1] == 1) {
                        unionFind.union(i * len2 + j, i * len2 + j - 1);
                    }
                    if (j + 1 < len2 && grid[i][j + 1] == 1) {
                        unionFind.union(i * len2 + j, i * len2 + j + 1);
                    }
                }
            }
        }
        int maxArea = 0;
        for (int i = 0; i < len1 * len2; i++) {
            maxArea = Math.max(maxArea, unionFind.rank[i]);
        }
        return maxArea;
    }

    class UnionFind {
        private int[] parent;
        private int[] rank;
        private int sum;

        public UnionFind(int[][] grid) {
            // 初始化岛屿数量为0,因为我们还没有遍历数组,不知道岛屿的数量
            sum = 0;
            int len1 = grid.length;
            int len2 = grid[0].length;
            parent = new int[len1 * len2];
            rank = new int[len1 * len2];
            for (int i = 0; i < len1; i++) {
                for (int j = 0; j < len2; j++) {
                    // 根节点指向自己
                    parent[i * len2 + j] = i * len2 + j;
                    // 如果这个地方是岛屿,那么该元素对应的集合内元素数量为1
                    if (grid[i][j] == 1) {
                        rank[i * len2 + j] = 1;
                        // 岛屿数量+1
                        sum++;
                    }
                }
            }
        }

        public int find(int x) {
            while (x != parent[x]) {
                x = parent[x];
            }
            return x;
        }

        public void union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY) {
                return;
            }
            // 如果根节点 rootX 的深度 > rootY。
            if (rank[rootX] > rank[rootY]) {
                // 那么将以rootY作为根节点的集合加入到rootX对应的集合当中
                rank[rootX] += rank[rootY];
                // 同时改变rootY的根节点,指向rootX。
                parent[rootY] = rootX;
            } else {
                // 反之
                rank[rootY] += rank[rootX];
                parent[rootX] = rootY;
            }
            // 岛屿数量-1
            sum--;
        }
    }
}

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

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

相关文章

Vue中如何进行日历展示与操作

在Vue中创建交互式日历应用 在Web开发中&#xff0c;创建一个交互式的日历应用是一项常见的任务。Vue.js作为一个流行的JavaScript框架&#xff0c;提供了许多便捷的工具和组件来简化日历的开发。本文将介绍如何使用Vue来创建一个简单但功能强大的日历应用&#xff0c;包括展示…

linux入门---信号的理解

目录标题 如何理解计算机中的信号如何查看计算机中的信号初步了解信号的保存和发送如何向目标进程发送信号情景一&#xff1a;使用键盘发送信号情景二&#xff1a;系统调用发送信号情景三&#xff1a;硬件异常产生信号情景四&#xff1a;软件条件产生信号 核心转储信号的两个问…

CentOS如何查找java安装路径

目 录 背景 详细步骤 1.使用指令查看有关javad安装路径 2.填入java路径 3.查找java安装路径 4.配置文件展示 背景 准备部署分布式hadoop的时候&#xff0c;校验hadoop版本发现java没配置 但是又有java版本信息 详细步骤 1.使用指令查看有关javad安装路径 java -verb…

敏捷项目管理中产品负责人– PO的核心职责

在敏捷项目管理中&#xff0c;产品负责人的角色非常重要。他们代表利益相关者&#xff0c;负责确保团队开发的产品具有价值、符合期望&#xff0c;满足客户需求。 产品负责人核心职责有&#xff1a; 规划产品的方向和路线图&#xff0c;决定产品要做什么。清晰的将产品的路线…

基于Java的银行记账与审核系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

使用win_b64做CATIA的开发测试

文章目录 一、把win_b64文件夹放在无中文的路径下二、启动环境文件编辑器三、新建环境文件四、集成CAA代码五、去用户环境目录查看环境文件是否生成六、关闭环境文件编辑器七、去桌面双击新建的快捷方式即可启动CATIA&#xff0c;进行测试八、进入对应的开发模块&#xff0c;查…

postgresql-聚合函数增强功能

postgresql-聚合函数增强功能 按季度统计入职员工 按季度统计入职员工 select -- extract截取&#xff0c;按季度进行统计入职员工总数 extract(year from hire_date), count(*) filter(where extract(quarter from hire_date) 1) "第一季度", count(*) filter(wh…

计算机竞赛 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

【软考】5.1 七层模型/局域网/TCP-IP协议

《网络功能和分类》 即计算机技术与通信技术相结合的产物&#xff0c;实现了远程通信、远程信息处理和资源共享计算机网络的功能&#xff1a;数据通信、资源共享、负载均衡&#xff08;给多个服务器负担&#xff09;、高可靠性 分布范围 拓扑结构分类 总线型&#xff1a;一般局…

Git小书系列笔记

Git准备 首先根据自己的系统安装git&#xff0c;安装成功后可以通过如下指令查看git版本。 使用Git之前&#xff0c;需要配置用户名称和电子邮件。 1.设置全局的用户名和电子邮件 git config --global user.name "Your Name" git config --global user.email &quo…

OpenGLES:绘制一个混色旋转的3D立方体

效果展示 混色旋转的3D立方体 一.概述 之前关于OpenGLES实战开发的博文&#xff0c;不论是实现相机滤镜还是绘制图形&#xff0c;都是在2D纬度 这篇博文开始&#xff0c;将会使用OpenGLES进入3D世界 本篇博文会实现一个颜色渐变、旋转的3D立方体 动态3D图形的绘制&#xf…

RabbitMQ-java使用消息队列

1 java操作消息队列 1.1 java实现生产者 新建一个springboot项目&#xff0c;导入依赖 <dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.14.2</version> </dependency>导入依…

ctfshow web入门 php特性 web113-web125

1.web113 和上题一样,/proc/self/root代表根目录&#xff0c;进行目录溢出&#xff0c;超过is_file能处理的最大长度就不认为是个文件了 payload: compress.zlib://flag.php /proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p roc/self/root/p…

操作系统内存管理相关

1. 虚拟内存 1.1 什么是虚拟内存 虚拟内存是计算机系统内存管理的一种技术&#xff0c;我们可以手动设置自己电脑的虚拟内存。不要单纯认为虚拟内存只是“使用硬盘空间来扩展内存“的技术。虚拟内存的重要意义是它定义了一个连续的虚拟地址空间&#xff0c;并且 把内存扩展到硬…

SLAM从入门到精通(用python实现机器人运动控制)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在ROS下面&#xff0c;开发的方法很多&#xff0c;可以是c&#xff0c;可以是python。大部分接口操作类的应用&#xff0c;其实都可以用python来开…

(五)激光线扫描-位移台标定

线激光属于主动测量方式,但是由于线激光的特性,我们只能通过提取激光中心线获取这一条线上的高度信息,那么要进行三维重建的话,就需要通过平移或者是旋转的方式,来让线激光扫描被测物体的完整轮廓,也就是整个表面。激光线的密度越高还原出来的物体越细腻,但由于数据量大…

计算机中丢失vcomp140.dll解决方案,可以使用这几个最新方法来修复

今天早上&#xff0c;当我打开电脑时&#xff0c;突然看到一个提示窗口&#xff0c;显示找不到 vcomp140.dll 文件。我一下子懵了&#xff0c;不知道这是怎么回事&#xff0c;也不知道如何解决这个问题。于是&#xff0c;我开始了寻找答案的旅程。 首先&#xff0c;我了解到 v…

<C++> 异常

C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 终止程序&#xff0c;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除0错误时就会终止程序。返回错误码&#xff0c;缺陷&#xff1a;需要程序员自己去查找对应的错误。如系统的…

Autosar诊断实战系列21-UDS连续帧(CF)数据接收代码级分析

本文框架 前言1. 长帧数据的连续帧接收2. 连续帧的处理前言 在本系列笔者将结合工作中对诊断实战部分的应用经验进一步介绍常用UDS服务的进一步探讨及开发中注意事项, Dem/Dcm/CanTp/Fim模块配置开发及注意事项,诊断与BswM/NvM关联模块的应用开发及诊断capl测试脚本开发等诊…