Java-数据结构-并查集<二>

news2024/11/25 6:46:20

一.并查集的简单介绍

二. 并查集的主要构成和实现方式

三.HashMap模板和数组模板

由于在下文的模板基本一致,不再每次都罗列,大体的模板如下,若有错误可以在leetcode找到对应的题目解答,已经附上连接。

HashMap


class UnionFind {
    private Map<Integer,Integer> father;
    
    public UnionFind() {
        father = new HashMap<Integer,Integer>();
    }
    
    public void add(int x) {
        if (!father.containsKey(x)) {
            father.put(x, null);
        }
    }
    
    public void merge(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        
        if (rootX != rootY){
            father.put(rootX,rootY);
        }
    }
    
    public int find(int x) {
        int root = x;
        
        while(father.get(root) != null){
            root = father.get(root);
        }
        
        while(x != root){
            int original_father = father.get(x);
            father.put(x,root);
            x = original_father;
        }
        
        return root;
    }
    
    public boolean isConnected(int x, int y) {
        return find(x) == find(y);
    }
}

数组

class UnionFind{
    public int[] parent;
    public int count;
    //初始化
    public UnionFind(int n){
        parent = new int[n];
        count = n;
        for(int i = 0; i< n; i++){
            parent[i] = i;
        }
    }
    //查找
    public int find(int x){
        while(x != parent[x]){
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }
    //合并节点
    public void union(int x, int y){
        if(find(x) == find(y)) return;
        parent[find(x)] = find(y);
        count--;
    }
    //是否为同一父节点,也就是是否联通
    public boolean isConnected(int x, int y){
        return find(x) == find(y);
    }
    //返回数量
    public int getCount(){
        return count;
    }
}

三. leetcode实战

1. leetcode547 省份数量

2. leetcode684 冗余连接

以上未出现部分圈全在在前篇文章,不再赘述

Java-数据结构-并查集<一>

3. leetcode1905 统计子岛屿

给你两个 m x n 的二进制矩阵 grid1 和 grid2 ,它们只包含 0 (表示水域)和 1 (表示陆地)。一个 岛屿 是由 四个方向 (水平或者竖直)上相邻的 1 组成的区域。任何矩阵以外的区域都视为水域。

如果 grid2 的一个岛屿,被 grid1 的一个岛屿 完全 包含,也就是说 grid2 中该岛屿的每一个格子都被 grid1 中同一个岛屿完全包含,那么我们称 grid2 中的这个岛屿为 子岛屿 。

请你返回 grid2 中 子岛屿 的 数目 。

输入:grid1 = [[1,1,1,0,0],[0,1,1,1,1],[0,0,0,0,0],[1,0,0,0,0],[1,1,0,1,1]], grid2 = [[1,1,1,0,0],[0,0,1,1,1],[0,1,0,0,0],[1,0,1,1,0],[0,1,0,1,0]]
输出:3
解释:如上图所示,左边为 grid1 ,右边为 grid2 。
grid2 中标红的 1 区域是子岛屿,总共有 3 个子岛屿。

 

整体思路:

1.遍历grid2数组,利用并查集把区域都连通起来
2.将grid的根节点都添加到HashSet中
3.到grid1中找HashSet中对应的节点是不是1

以示例一为例

那么,在使用并查集后,我们的un2里面陆地联通的区域就是:
0,11,15,17,21
那么对应的HashSet里面也会是{0,11,15,17,21}
然后遍历grid1,找到HashSet对应的位置,是1的话,就可以符合题目要求。
HashSet中的11是不符合要求的,因为对应的grid1里面是0,同样
HashSet中的17也是同样的道理。 

主题函数部分(模板在上方)

class Solution {
    public int countSubIslands(int[][] grid1, int[][] grid2) {
        int row1 = grid1.length;
        int col1 = grid1[0].length;
        int row2 = grid2.length;
        int col2 = grid2[0].length;
        UnionFind un2 = new UnionFind(row2*col2);
        //遍历grid2
        for(int i = 0; i < row2; i++){
            for(int j = 0; j < col2; j++){
                if(grid2[i][j] == 0) continue;
                if(i+1 < row2 && grid2[i+1][j] == 1) un2.union(i*col2+j, i*col2+j+col2);
                if(j+1 < col2 && grid2[i][j+1] == 1) un2.union(i*col2+j, i*col2+j+1);
            }
        }
        //把grid2联通区域的根节点放进set中
        HashSet<Integer> set = new HashSet<>();
        for(int i = 0; i < row2; i++){
            for(int j = 0; j < col2; j++){
                if(grid2[i][j] == 1){
                    set.add(un2.find(i*col2+j));
                }     
            }
        }
        //去grid1查找对应的点是不是1
        for(int i = 0; i < row1; i++){
            for(int j = 0; j < col1; j++){
                 if(grid1[i][j] == 0){
                    set.remove(un2.find(i*col2+j));
            }    
            }
        }
       return set.size();
    }
}

 原题解连接(若模板有出入可参考):

Java 并查集 超简单易懂附模板

 

4. leetcode1254 统计封闭岛屿的数目

二维矩阵 grid 由 0 (土地)和 1 (水)组成。岛是由最大的4个方向连通的 0 组成的群,封闭岛是一个 完全 由1包围(左、上、右、下)的岛。

请返回 封闭岛屿 的数目。

示例 1:
输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2
解释:
灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。

 

 整体思路

1. 用并查集走一遍grid,把岛屿都联通起来
2. 用HashSet添加岛屿的根节点
3. 把处于边上,也就是下图中红色部分排除掉(注意,此时排除的是对应是陆地的那个节点的根节点)

 也就是

if(grid[i][j] == 0){
    if(i == 0 || j == 0 || i == row-1 || j == col -1) set.remove(un.find(i*col+j));    
}

主函数中

if(i == 0 || j == 0 || i == row-1 || j == col -1)

可以排除掉图中红色的部分。

主函数部分

class Solution {
    public int closedIsland(int[][] grid) {
        int row = grid.length;
        int col = grid[0].length;
        UnionFind un = new UnionFind(row*col);
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 1) continue;
                if(i+1 < row && grid[i+1][j] == 0) un.union(i*col+j, i*col+j+col);
                if(j+1 < col && grid[i][j+1] == 0) un.union(i*col+j, i*col+j+1);
            }
        }
        HashSet<Integer> set = new HashSet<>();
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 0) set.add(un.find(i*col+j));    
            }
        }
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 0){
                    if(i == 0 || j == 0 || i == row-1 || j == col -1) set.remove(un.find(i*col+j));    
                }
            }
        }
        return set.size();
    }
}

原题解连接(若模板有出入可参考):
Java 并查集 思路简单附模板

 

5. leetcode130 被围绕的区域

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。

示例 1:
输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 
任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。
如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。

整体思路:

1.这题和1254. 统计封闭岛屿的数目思路一样
2.只不过要的是外面的岛屿,而1254里要的是里卖的。

思路

1. 并查集走一遍,得到所有的父节点
2. 把所有的父节点添加到set中
3. 把边上的所有的岛排除掉(即排除边上的是'O'的父节点)(即下图红色的部分从set中排除)
4. 把剩在set中的父节点中的是'O'的都变成'X'

主函数

class Solution {
    public void solve(char[][] board) {
        int row = board.length;
        int col = board[0].length;
        UnionFind un = new UnionFind(row*col);
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(board[i][j] == 'X') continue;
                if(i+1 < row && board[i+1][j] == 'O') un.union(i*col+j, i*col+j+col);
                if(j+1 < col && board[i][j+1] == 'O') un.union(i*col+j, i*col+j+1);
            }
        }
         HashSet<Integer> set = new HashSet<>();
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(board[i][j] == 'O'){
                    set.add(un.find(i*col +j));
                }
            }
        }
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(board[i][j] == 'O'){
                    if(i == 0 || j == 0 || i == row-1 || j == col-1){
                    set.remove(un.find(i*col +j));
                    }
                }
            }
        }
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(board[i][j] == 'O'){
                    if(set.contains(un.find(i*col +j))){
                        board[i][j] = 'X';
                    }
                }
            }
        }
    }
}

原题解连接(若模板有出入可参考):

Java 并查集 思路简单附模板

6. leetcode1319 连通网络的操作次数

用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。

网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。

给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。

输入:n = 4, connections = [[0,1],[0,2],[1,2]]
输出:1
解释:拔下计算机 1 和 2 之间的线缆,并将它插到计算机 1 和 3 上。

 思路:

1. 我们总共有的线的数量就是connections数组的数量
2. 连接n个电脑我们最少需要n-1条线
3. 并查集过后我们把已经连接的电脑看作一个整体m,如果线够用的情况下我们只需要m-1条线,不必在意具体要怎么连接

以示例2为例

示例 2:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
输出:2

那么在并查集过后,并查集的数量是3,减一就可以得到我们需要的答案。

主函数

class Solution {
    public int makeConnected(int n, int[][] connections) {
        int len = connections.length;
        if(len < n-1) return -1;
        UnionFind un = new UnionFind(n);
        for(int i = 0; i < len; i++){
            un.union(connections[i][0],connections[i][1]);
        }
        return un.getcount()-1;
    }
}

原题解连接(若模板有出入可参考):

Java 并查集 简单易懂附模板

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

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

相关文章

本周大新闻|苹果首款MR没有主打卖点;Meta认为AI是AR OS的基础

​本周XR大新闻&#xff0c;AR方面&#xff0c;苹果首款MR或没有主打卖点&#xff0c;反而尽可能支持更多App和服务&#xff1b;扎克伯格表示基于AI的AR眼镜操作系统是下一代计算平台的基础&#xff1b;微软芯片工程VP Jean Boufarhat加入Meta芯片团队&#xff1b;Humane展示了…

[计算机图形学]高级光线传播与复杂外观建模(前瞻预习/复习回顾)

本篇不涉及技术细节* 一、高级光线传播* 1.有偏和无偏估计 无偏估计&#xff0c;比如我们在之前做路径追踪的时候&#xff0c;我们用许多样本去近似定积分的值&#xff0c;无论我们取的样本数量是多少&#xff0c;它的期望永远是对的&#xff0c;也就是我们真实的定积分的值&…

Python入门(一)Python概述与环境搭建

Python概述与环境搭建 1.概述1.1版本及下载1.2 Python 特点 2.环境搭建3.第一个程序“hello&#xff0c;world”4.可能会存在的问题 1.概述 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

【WAF】雷池waf升级体验

文章目录 前言一、更新二、功能体验1.仪表板2.自定义规则&#xff1a;3. 通用配置&#xff1a; 更新总结新增优化&#xff1a; 前言 最近雷池有比较大的更新&#xff0c;安装可以参考以前文章雷池waf安装&#xff0c;更新了数据统计也就是仪表板和自定义规则和通用配置还有IP高…

AI行为分析预警系统 opencv

AI行为分析预警系统通过pythonopencv网络模型Ai视觉智能分析技术&#xff0c;AI行为分析预警系统可以对实际场景下如车间、电力场景、化工场景、工业生产场景下的人员作业操作行为规范进行有针对性的定制开发&#xff0c;根据每个项目的不同的识别预警需求。OpenCV可以在不同的…

BEV(0)---Transformer

1 Transformer Transformer是一个Sequence to Sequence model&#xff0c;特别之处在于它大量用到了self-attention&#xff0c;替代了RNN&#xff0c;既考虑了Sequence的全局信息也解决了并行计算的问题。 1.1 self-attention&#xff1a; ①. 输入x1 ~ x4为一个sequence&…

Mysql-SQL优化

SQL优化 插入数据优化1&#xff09;批量插入数据2&#xff09;手动控制事务3&#xff09;主键顺序插入大批量插入数据 主键优化order by优化group by优化limit优化count优化update优化小结 插入数据优化 插入数据优化主要是对于insert进行批量插入时优化&#xff0c;下面我们就…

验证二叉搜索树-递归双指针法

1题目 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff1a…

初识springboot【手把手教你搭建springboot项目】+springboot日志详解【超详细】

目录 一.springboot的概念 1.什么是springboot&#xff1f; 二.使用springboot进行开发的优势 springboot的设计原则是什么&#xff0c;使用springboot进行开发具有怎样的优势&#xff1f;&#xff08;M&#xff09; 三.手把手搭建一个springboot项目 ①创建项目并选择依赖…

枚举二进制数的子集

思想&#xff1a; 如1011的二进制子集有1011&#xff0c;1010&#xff0c;1001&#xff0c;1000&#xff0c;0011&#xff0c;0010&#xff0c;0001&#xff0c;0000 思想是每次对当前最小子元素-1与目标x取与运算。枚举到0为止。 成立原因&#xff1a;因为我们是由大到小&a…

Python使用AI photo2cartoon制作属于你的漫画头像

Python使用AI photo2cartoon制作属于你的漫画头像 1. 效果图2. 原理3. 源码参考 git clone https://github.com/minivision-ai/photo2cartoon.git cd ./photo2cartoon python test.py --photo_path images/photo_test.jpg --save_path images/cartoon_result.png1. 效果图 官方…

计算机组成原理 存储器(下)

Cache和主存之间的映射: Cache的基本结构 Cache存储体以块为单位和主存交换信息&#xff0c;地址变换机制是由CPU送往主存的数据转换为Cacche的地址&#xff0c;主存和Cache的大小相同所以 &#xff0c;如果能够建立对应关系&#xff0c;则代表命中。 Cache的读写操作 写操作…

链表:常见面试题-根据大小划分区域

将单向链表按某值划分为左边小、中间相等、右边大的形式 1&#xff09;将链表放入数组里&#xff0c;在数组上做partition&#xff08;类似快排&#xff09;&#xff0c;这是笔试时推荐的写法 2&#xff09;分为小、中、大三部分&#xff0c;再把各个部分之间串起来&#xff…

1. 异常概述

目录 1.1 什么是生活的异常 1.2 什么是程序的异常 1.3 异常的抛出机制 1.4 如何对待异常 1.1 什么是生活的异常 男主角小明每天开车上班&#xff0c;正常车程 1 小时。但是&#xff0c;不出意外的话&#xff0c;可能会出现意外。 出现意外&#xff0c;即为异常情况。我们会…

自动化测试和selenium的使用

目录 自动化测试定义 为什么选择selenium来作为我们web自动化测试的工具&#xff1f; 自动化测试定位元素 使用cssSelector定位 使用XPath 定位 操作测试对象 模拟手动从键盘输入 点击对象 获取页面文本 清除对象输入的文本内容 添加等待&#xff08;三种方式&#…

00 SQL介绍

什么是SQL Structured Query Language&#xff1a;结构化查询语言 其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式可能会存在一些不一样的地方&#xff0c;我们称为“方言”。 SQL通用语法 SQL 语句可以单行或多行书写&#xff0c;以分号结尾。 可使用空…

干货 | 如何让Zotero更加强大?这六个插件是您的不二之选!

Hello,大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ Zotero是由安德鲁w梅隆基金会斯隆基金会以及美国博物馆和图书馆服务协会资助开发&#xff0c;是一个免费易用的文献管理软件&#xff0c;可协助我们收集、管理及引用研究资源&#xff0c;包括期刊、书籍…

系统集成项目管理工程师 笔记(第20章:知识产权管理、第21章:法律法规和标准规范)

文章目录 20.1.2 知识产权的特性 58420.2.1 著作权及邻接权 58520.2.2 专利权 58920.2.3 商标权 59221.3 诉讼时效 59921.6.3 标准分级与标准类型 60321.7.2 信息系统集成项目管理常用的技术标准 6061、基础标准2、开发标准3、文档标准4、管理标准 第20章 知识产权管理 584 20.…

LeetCode刷题系列之----->(指针玩转链表篇)(三)

&#x1f349;博客主页&#xff1a;阿博历练记 &#x1f4d6;文章专栏&#xff1a;数据结构与算法 &#x1f50d;代码仓库&#xff1a;阿博编程日记 &#x1f339;欢迎关注&#xff1a;欢迎友友们点赞收藏关注哦 文章目录 &#x1f58b;1.题目描述&#x1f4a1; 逻辑分析&#…

Java+Selenium常用方法梳理

五一假期&#xff0c;祝大家节日快乐。本篇继续自动化测试知识梳理。selenium 自己封装好用的方法&#xff0c;如悬停&#xff0c;句柄获取&#xff0c;可直接调用&#xff0c;实现自己的需求。 1、多窗口切换 即获取页面的句柄&#xff0c;来实现页面的切换&#xff0c;以ha…