数据结构与算法--并查集结构

news2025/1/24 5:03:19

数据结构与算法--并查集结构

  • 1 岛问题
  • 2 并查集结构

 


 

1 岛问题

 

一个矩阵中只有0和1两种值,每个位置都可以和自己的上、下、左、右 四个位置相连,如果有一片1连在一起,这个部分叫做一个岛,求一个矩阵中有多少个岛?
【举例】
001010
111010
100100
000000
这个矩阵中有三个岛

coding

package com.chao;

/**
 * @author Mrchao
 * @version 1.0.0
 * @date 2023-10-15
 */
public class CountIslandTest {

    public static void main(String[] args) {
        int[][] m = {
                {0, 0, 1, 0, 1, 0},
                {1, 1, 1, 0, 1, 0},
                {1, 0, 0, 1, 0, 0},
                {0, 0, 0, 0, 0, 0}
        };
        System.out.println(countIsland(m));
    }

    public static int countIsland(int[][] m) {
        if (m == null || m[0] == null) {
            return 0;
        }

        int M = m.length;//行数
        int N = m[0].length;//列数

        int ret = 0;
        /**
         * 遍历一遍岛屿 碰到 1 则进行一次感染过程
         */
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (m[i][j] == 1) {
                    ret++;
                    infect(m, i, j, M, N);
                }
            }
        }
        return ret;
    }

    /**
     * 二维数组 m 中与 m[i][j]直接相邻 或间接相邻的点 全部修改为 2
     *
     * @param m
     * @param i
     * @param j
     * @param M 二维数组行数
     * @param N 二维数组的列数
     */
    public static void infect(int[][] m, int i, int j, int M, int N) {
        if (i < 0 || i >= M || j < 0 || j >= N || m[i][j] != 1) {
            return;
        }
        m[i][j] = 2;
        infect(m, i - 1, j, M, N);
        infect(m, i + 1, j, M, N);
        infect(m, i, j - 1, M, N);
        infect(m, i, j + 1, M, N);
    }
}

 

时间复杂度 O ( M ∗ N ) O(M * N) O(MN)

 


 

2 并查集结构

 

并查集对外提供的操作 :

  1. 集合的合并 合并两个集合 形成一个更大的集合

  2. 集合的查询 判断两个元素是否在同一个集合中

如图所示

 

public class UnionFindTest {
    // 并查集中的元素
    public static class Element<V> {
        public V value;

        public Element(V value) {
            this.value = value;
        }
    }

    public static class UnionFindSet<V> {
        public Map<V, Element<V>> elementMap;// key 某个具体的值 value key 对应的元素
        public Map<Element<V>, Element<V>> fatherMap;// key 并查集中的某个元素  value : 该元素的父 当前元素向上指的元素
        public Map<Element<V>, Integer> sizeMap;// key 代表元素  value 该集合中元素的个数

        public UnionFindSet(List<V> list) {
            elementMap = new HashMap<>();
            fatherMap = new HashMap<>();
            sizeMap = new HashMap<>();
            for (V v : list) {
                Element<V> element = new Element<>(v);// 创建元素
                elementMap.put(v, element);
                fatherMap.put(element, element); // 当前每个节点的父都是自己
                sizeMap.put(element, 1); // 每个集合中的元素的个数都是 1
            }
        }

        /**
         * 给定一个元素一直往上找  把代表元素返回
         *
         * @param e
         * @return
         */
        private Element<V> findHead(Element<V> e) {
            Stack<Element<V>> path = new Stack<>();
            // 没有找到父 就一直找 
            while (e != fatherMap.get(e)) {
                path.push(e);
                e = fatherMap.get(e);
            }
            // 到此找到了 父元素
            // 把沿途遍历过的所有的元素都挂在当前的父元素上
            while (!path.isEmpty()) {
                fatherMap.remove(path.pop(), e);
            }
            return e;
        }

        /**
         * 判断 两个值是否在同一个集合中
         *
         * @param v1
         * @param v2
         * @return
         */
        public boolean isSameSet(V v1, V v2) {
            if (elementMap.containsKey(v1) && elementMap.containsKey(v2)) { // v1 v2 初始化过
                return findHead(elementMap.get(v1)) == findHead(elementMap.get(v2));
            }
            return false;
        }

        /**
         * 将两个值合并为一个集合
         *
         * @param v1
         * @param v2
         */
        public void union(V v1, V v2) {
            if (elementMap.containsKey(v1) && elementMap.containsKey(v2)) { // 被初始化过
                Element<V> fHead = findHead(elementMap.get(v1));
                Element<V> sHead = findHead(elementMap.get(v2));
                if (fHead != sHead) { // 不在同一个集合中 才进行合并
                    // 数据较少的集合的顶端挂在数据较多的数据的顶端的底下
                    Element<V> big = sizeMap.get(fHead) >= sizeMap.get(sHead) ? fHead : sHead;
                    Element<V> small = big == fHead ? sHead : fHead;
                    fatherMap.put(small, big);
                    sizeMap.put(big, sizeMap.get(fHead) + sizeMap.get(sHead));
                    sizeMap.remove(small);
                }
            }
        }
    }
}

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

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

相关文章

FutureTask的测试使用和方法执行分析

FutureTask类图如下 java.util.concurrent.FutureTask#run run方法执行逻辑如下 public void run() {if (state ! NEW ||!RUNNER.compareAndSet(this, null, Thread.currentThread()))return;try {Callable<V> c callable;if (c ! null && state NEW) {V res…

【软考】9.4 图的概念/存储/遍历/最小生成树/拓扑/查找

《图》 图的存储&#xff08;顶点和边&#xff09; 邻接矩阵&#xff1a;适合边数较多的图&#xff0c;不易造成浪费无向图&#xff1a;不分方向&#xff1b;对称矩阵 邻接链表&#xff1a;顶点&#xff0c;边——>&#xff08;编号&#xff0c;权值&#xff09;&#xff1b…

二维数组的行指针与列指针

二维数组的行指针与列指针 笔记来源&#xff1a;懒猫老师-C语言-用指针访问二维数组&#xff08;指针与二维数组&#xff09; 声明&#xff1a;本文笔记来自bili懒猫老师&#xff0c;仅供学习参考 回顾一维数组 int a[3];//其中a或a[0]是数组首地址 //a1指向第二个元素的地址…

The SDK location is inside Studio install location 解决

The SDK location is inside Studio install location 解决 安装 Android Studio SDK 时提示&#xff1a;The SDK location is inside Studio install location 解决 问题&#xff1a; 由于 SDK 与 编辑器(Android Studio)的安装在同一目录下所以报错。 解决 你需要在 Andro…

五、RocketMQ发送顺序消息

顺序消息的应用场景 在有序事件处理、撮合交易、数据实时增量同步等场景下&#xff0c;异构系统间需要维持强一致的状态同步&#xff0c;上游的事件变更需要按照顺序传递到下游进行处理。 例如需要保证一个订单的生成、付款和发货&#xff0c;这三件事情是被顺序执行的。 如…

C# OpenVINO Det 物体检测

效果 耗时 elephant:89% Preprocess: 0.00ms Infer: 47.21ms Postprocess: 11.63ms Total: 58.84ms 项目 代码 using OpenCvSharp; using Sdcb.OpenVINO; using Sdcb.OpenVINO.Natives; using System; using System.Diagnostics; using System.Drawing; using System.Text; …

淘宝店铺订单详情接口,淘宝店铺订单列表数据,淘宝店铺订单物流接口,淘宝店铺订单线下发货接口-

淘宝店铺订单详情接口可以理解为淘宝开放平台&#xff08;Taobao Open Platform&#xff09;提供的API接口1。 该接口可以获取淘宝店铺的订单详情&#xff0c;包括订单号、买家昵称、收货人姓名、收货地址、邮编、电话、商品描述、价格等信息。开发者可以在淘宝开放平台注册一…

使用winUSB进行USB开发

什么是winUSB WinUSB是Windows操作系统提供的一种通用USB驱动程序&#xff0c;用于简化USB设备的开发和使用。它是一个用户模式驱动程序&#xff0c;可以在Windows XP及更高版本的操作系统上使用。WinUSB提供了一组API和工具&#xff0c;使开发人员能够与USB设备进行通信&…

C++11可变参数模板

文章目录 1.可变参数模板的介绍1.1C语言中的可变参数1.2C98/C11的类模板和函数模板1.3可变参数的函数模板1.4展开参数包递归展开初始化列表展开 2.可变参数模板的应用 1.可变参数模板的介绍 1.1C语言中的可变参数 1.2C98/C11的类模板和函数模板 C98/03&#xff0c;类模版和函…

Numpy(一)简介与基本使用

Numpy&#xff08;一&#xff09;简介与基本使用 一、Numpy简介 1.Numpy是一个运行速度非常快的数学库&#xff0c;主要用于数组计算 2.包含&#xff1a;N维数组对象ndarray、广播功能函数、整合C/C/Fortran代码工具、包含线性代数/傅里叶变换/随机数生成等功能 3.优点&…

ChatGPT快速入门

ChatGPT快速入门 一、什么是ChatGPT二、ChatGPT底层逻辑2.1 实现原理2.2 IO流程 三、ChatGPT应用场景3.1 知心好友3.2 文案助理3.3 创意助理3.4 角色扮演 一、什么是ChatGPT ChatGPT指的是基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型的对话生成系…

python字典、列表排序,从简单到复杂

因工作原因&#xff0c;需要频繁对python字典(dict)、列表(list)等进行各种各样的排序&#xff0c;发现网上这块的资料又多又杂&#xff0c;尤其涉及到lambda的&#xff0c;让人觉得难以理解看不下去&#xff0c;因此写了这篇文章&#xff0c;从简单到复杂&#xff0c;配合例子…

【Eclipse】安装教程

首先打开官网&#xff1a;Eclipse Downloads | The Eclipse Foundation 这里我选择了下载最新版本 下载好后&#xff0c;双击下载的文件 &#xff0c;即可进入到安装页面 点击第一个进行安装&#xff1a; 最后安装成功&#xff01; 补充&#xff1a; 【Eclipse】安装JAVA EE插…

Jmter接口网站压力测试工具使用记录

1.首先下载Jmeter 官方地址&#xff1a;Apache JMeter - Apache JMeter™ 回到顶部 2.安装Jmeter 把下载的文件进行解压&#xff0c;产生如下目录&#xff1a; 打开bin文件夹下的jmeter.bat文件及进入程序的主界面窗体jmeter.log是日志文件。 主意&#xff1a;需要配置java环…

河北专升本(C语言)

目录 一&#xff1a;C语言的构成特点 二: 数据类型 三: 常量、变量、运算符及表达式 &#xff08;一&#xff09;标识符 &#xff08;二&#xff09;常量 &#xff08;三&#xff09;变量&#xff1a;其值可以改变的量 &#xff08;四&#xff09;各种类型数据混合运算 &…

打印编译程序固件的环境信息

在编译程序固件的时候&#xff0c;我们常常会有一个软件版本号&#xff0c;用来区分不同的版本&#xff0c;有时候又没变化软件版本号&#xff0c;重新发两个debug版本给测试验证&#xff0c;那我们就需要在程序中埋入一些环境信息&#xff0c;下面有两种方法来加入一下简单的信…

APP 备案公钥、签名 MD5、SHA-1、SHA-256获取方法。

公钥和 MD5 值可以通过安卓开发工具、Keytool、Jadx-GUI 等多种工具获取&#xff0c;最简单的就是以 jadx-gui 为例。 1.下载 jadx-gui 工具 &#xff0c;点击此处 下载 jadx-gui 工具。 2.下载完成后&#xff0c;解压压缩包&#xff0c;双击 jadx-gui-1.4.7.exe 运行。 3.…

Neo4j入门基础:CREATE,DELETE,SET,REMOVE(看不懂我直接吃...)

1. 创建节点 1.1 创建一个节点 create (s:student1)创建一个标签为student1的节点 1.2 创建多个节点 create (s2:student2),(s3:student3)同时创建两个节点&#xff0c;标签分别为&#xff1a;student2&#xff0c;student3 1.3 创建节点并附带&#xff08;多个&#xff0…

MAC上设置IDEA如何一个窗口打开多个项目,多个tab

1、IDEA一个窗口打开多个项目 如果你打开了多个项目、每次切换都要半天&#xff0c;想让项目都汇聚到top栏 点击 Window - Merge All Project Windows 即可 但是这样比较挫&#xff0c;每次打开新的项目都还是会重新打开一个IDEA窗口 so&#xff0c;如何设置项目在同一个窗口…

树模型(一)孤立森林

孤立森林&#xff08;Isolation Forest&#xff09;算法是西瓜书作者周志华老师的团队研究开发的算法&#xff0c;一般用于结构化数据的异常检测。 异常的定义 针对于不同类型的异常&#xff0c;要用不同的算法来进行检测&#xff0c;而孤立森林算法主要针对的是连续型结构化…