08数据结构与算法刷题之【并查集】篇

简介: 08数据结构与算法刷题之【并查集】篇

基础知识点


并查集(Union-find Data Structure)是一种树型的数据结构。它的特点是由子结点找到父亲结点,用于处理一些不交集(Disjoint Sets)的合并及查询问题。


Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。

Union:将两个子集合并成同一个集合。


剑指offer


剑指 Offer II 116. 省份数量【中等】


学习:leetcode/并查集/深度优先搜索/朋友圈问题/岛屿问题


题目链接:剑指 Offer II 116. 省份数量


题目内容:


有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
返回矩阵中 省份 的数量。


思路:


1、并查集


复杂度分析:时间复杂度O(nm);空间复杂度O(n)


class Solution {
    public int findCircleNum(int[][] isConnected) {
        UnionFind uf = new UnionFind(isConnected);
        int len1 = isConnected.length;
        int len2 = isConnected[0].length;
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                if (isConnected[i][j] == 0) continue;
                uf.merge(i, j);
            }
        }
        return uf.size;
    }
}
class UnionFind {
    public int size;
    private int[] parent;
    private int[] weight;
    public UnionFind(int[][] isConnected) {
        int n = isConnected.length;
        this.size = n;
        this.parent = new int[n];
        this.weight = new int[n];
        for (int i = 0; i < n; i++) {
            this.parent[i] = i;
            this.weight[i] = 1;
        }
    }
    public int find(int x) {
        if (x == parent[x]) {
            return x;
        }else {
            parent[x] = find(parent[x]);
            return parent[x];
        }
    }
    public void merge(int x, int y) {
        int _x = find(x);
        int _y = find(y);
        if (_x == _y) return;
        if (weight[_x] < weight[_y]) {
            int temp = _x;
            _x = _y;
            _y = temp;
        }
        parent[_y] = parent[_x];
        weight[_x] += weight[_y];
        --size;
    }
}



leetcode


剑指 Offer II 105. 岛屿的最大面积【中等】


题目链接:剑指 Offer II 105. 岛屿的最大面积


题目内容;


思路:


1、dfs深搜


复杂度分析:时间复杂度O(mn);空间复杂度O(mn)


class Solution {
    private int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private int max = 0;
    public int maxAreaOfIsland(int[][] grid) {
        //遍历一遍,若是为1进行dfs,然后res+1
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == 1) {
                    max = Math.max(dfs(grid, i, j, 1), max);
                }
            }
        }
        return max;
    }
    public int dfs(int[][] grid, int i, int j, int area) {
        //边界
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[i].length) {
            return 0;
        }
        //若是为1的进行标注并继续往下执行
        if (grid[i][j] == 0) {
            return 0;
        }
        //地图位置进行标注
        grid[i][j] = 0;
        //四个方向进行执行
        int res = 1;
        for (int[] direction: directions) {
            res += dfs(grid, i + direction[0], j + direction[1], area + 1);
        }
        return res;
    }
}



2、并查集


复杂度分析:时间复杂度O(mn);空间复杂度O(mn)


class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        //初始化并查集
        UnionFind unionFind = new UnionFind(grid);
        int iLen = grid.length;
        int jLen = grid[0].length;
        //遍历一遍,若是为1进行dfs,然后res+1
        for (int i = 0; i < iLen; i++) {
            for (int j = 0; j < jLen; j++) {
                if (grid[i][j] == 0) continue;
                //四个方向
                if (i - 1 >= 0 && grid[i - 1][j] == 1) 
                    unionFind.merge(i * jLen + j, (i - 1) * jLen + j);
                if (i + 1 < iLen && grid[i + 1][j] == 1) 
                    unionFind.merge(i * jLen + j, (i + 1) * jLen + j);
                if (j - 1 >= 0 && grid[i][j - 1] == 1) 
                    unionFind.merge(i * jLen + j, i * jLen + j - 1);
                if (j + 1 < jLen && grid[i][j + 1] == 1) 
                    unionFind.merge(i * jLen + j, i * jLen + j + 1);
            }
        }
        int max = 0;
        for (int i = 0; i < iLen; i++) {
            for (int j = 0; j < jLen; j++) {
                max = Math.max(max, unionFind.weight[i * jLen + j]);
            }
        }
        return max;
    }
}
class UnionFind {
    public int size;
    public int[] parent;
    public int[] weight;
    public UnionFind(int[][] grid) {
        int len1 = grid.length;
        int len2 = grid[0].length;
        this.size = len1 * len2;
        this.parent = new int[size];
        this.weight = new int[size];
        //初始化
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                parent[i * len2 + j] = i * len2 + j;
                //根据岛屿是否为1来设置权重是否为1
                if (grid[i][j] == 1) {
                    weight[i * len2 + j] = 1;
                }else {
                    weight[i * len2 + j] = 0;
                }
            }
        }
    }
    public int find(int x) {
        if (x == parent[x]) {
            return x;
        }else {
            parent[x] = find(parent[x]);
            return parent[x];
        }
    }
    public void merge(int x, int y) {
        int _x = find(x);
        int _y = find(y);
        if (_x == _y) return;
        if (weight[_x] < weight[_y]) {
            int temp = _x;
            _x = _y;
            _y = temp;
        }
        //连通结点
        parent[_y] = _x;
        weight[_x] += weight[_y];
        --size;
    }
}
相关文章
|
1月前
|
算法 开发者 计算机视觉
燃爆全场!Python并查集:数据结构界的网红,让你的代码炫酷无比!
在编程的世界里,总有一些数据结构以其独特的魅力和高效的性能脱颖而出,成为众多开发者追捧的“网红”。今天,我们要介绍的这位明星,就是Python中的并查集(Union-Find)——它不仅在解决特定问题上大放异彩,更以其优雅的设计和强大的功能,让你的代码炫酷无比,燃爆全场!
31 0
|
2月前
|
算法 JavaScript 前端开发
第一个算法项目 | JS实现并查集迷宫算法Demo学习
本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。
第一个算法项目 | JS实现并查集迷宫算法Demo学习
|
1月前
|
存储 算法 Python
火箭般的提升!学会Python并查集,让你的算法能力飞跃新高度!
火箭般的提升!学会Python并查集,让你的算法能力飞跃新高度!
33 1
|
2月前
|
Python
逆天改命!掌握Python并查集,数据结构难题从此不再是你的痛!
在编程旅程中,遇到棘手的数据结构难题是否让你苦恼?别担心,Python并查集(Union-Find)是你的得力助手。这是一种高效处理不相交集合合并及查询的数据结构,广泛应用于网络连通性、社交网络圈子划分等场景。通过维护每个集合的根节点,它实现了快速合并与查询。本文将介绍并查集的基本概念、应用场景以及如何在Python中轻松实现并查集,帮助你轻松应对各种数据结构挑战。
34 3
|
26天前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
12 0
|
2月前
|
算法 计算机视觉 Python
Python并查集大揭秘:让你在算法界呼风唤雨,秒杀一切复杂场景!
在编程与算法的广袤天地中,总有一些工具如同神兵利器,能够助你一臂之力,在复杂的问题前游刃有余。今天,我们就来深入探讨这样一件神器——Python并查集(Union-Find),看看它是如何让你在算法界呼风唤雨,轻松应对各种复杂场景的。
63 2
|
2月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
2月前
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
27 0
|
2月前
|
算法 开发者 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
在编程的浩瀚宇宙中,数据结构如同基石,构建了解决问题的坚实框架。而并查集(Union-Find),这位数据结构界的“肌肉男”,以其独特的魅力和强大的功能,让无数开发者在面对复杂关系处理时,都能感受到前所未有的从容与自信。今天,就让我们一同揭开并查集的神秘面纱,看看它是如何成为你编程路上的得力助手的。
29 0
|
2月前
|
算法 程序员 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
并查集,一种处理不相交集合合并与查询的数据结构,被誉为编程的“肌肉男”。它提供Find(找根节点)和Union(合并集合)操作,常用于好友关系判断、图像处理、集合合并等。Python实现中,路径压缩和按秩合并优化效率。并查集的高效性能使其成为解决问题的强大工具,助力程序员应对复杂挑战。
27 0