IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【小航的算法日记】并查集 -> 正文阅读

[数据结构与算法]【小航的算法日记】并查集

一、概念

二、模板

int n = 1005; // 节点数量3 到 1000
int father[1005];

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}
// 并查集里寻根的过程
int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]);
}
// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return ;
    father[v] = u;
}
// 判断 u 和 v是否找到同一个根
bool same(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

并查集主要有三个功能。

  1. 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
  2. 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
  3. 判断两个节点是否在同一个集合,函数:same(int u, int v),就是判断两个节点是不是同一个根节点

注:

合并:

在这里插入图片描述

路径压缩:
在这里插入图片描述

三、例题

题:684. 冗余连接

树可以看成是一个连通且 无环无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。

示例 1:
在这里插入图片描述

输入: edges = [[1,2], [1,3], [2,3]]
输出: [2,3]

示例 2:
在这里插入图片描述

输入: edges = [[1,2], [2,3], [3,4], [1,4], [1,5]]
输出: [1,4]

提示:

n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ai < bi <= edges.length
ai != bi
edges 中无重复元素
给定的图是连通的 

解:

解题思路:

题目大意是给定一个无向图,删除一条边,使得结果图是一个有n个节点的树(其实就是找环,删边)

  1. 遍历每一条边,如果边的两个节点不在同一个集合中,就加入集合。
  2. 如果边的两个节点已经出现在集合中了,说明如果着边的两个节点已经连在一起了,如果在加入这条边一定会出现环。

AC代码:

class Solution {
    int n = 1005; // 节点数量从3-1000
    int father[] = new int[1005];
    // 并查集初始化
    void init() {
        for(int i = 0; i < n; ++ i) father[i] = i;
    }
    // 并查集寻根
    int find(int u) {
        if(u == father[u]) {
            return u;
        }
        father[u] = find(father[u]);
        return father[u];	
    }
    // 将 v -> u 这条边加入并查集
    void join(int u, int v) {
        u = find(u);
        v = find(v);
        if(u != v) father[v] = u; 
    }
    // 判断 u 和 v 是否找到同一个根
    boolean isSame(int u, int v) {
        return find(u) == find(v);
    }
    public int[] findRedundantConnection(int[][] edges) {
        init();
        for(int i = 0; i < edges.length; ++ i) {
            if(isSame(edges[i][0], edges[i][1])) return edges[i];
            else join(edges[i][0], edges[i][1]);
        }
        return new int[]{};
    }
    
}

题:685. 冗余连接 II

在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。

输入一个有向图,该图由一个有着 n 个节点(节点值不重复,从 1 到 n)的树及一条附加的有向边构成。附加的边包含在 1 到 n 中的两个不同顶点间,这条附加的边不属于树中已存在的边。

结果图是一个以边组成的二维数组 edges 。 每个元素是一对 [ui, vi],用以表示 有向 图中连接顶点 ui 和顶点 vi 的边,其中 ui 是 vi 的一个父节点。

返回一条能删除的边,使得剩下的图是有 n 个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。

示例 1:
在这里插入图片描述

输入:edges = [[1,2],[1,3],[2,3]]
输出:[2,3]

示例 2:
在这里插入图片描述

输入:edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
输出:[4,1]

提示:

n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ui, vi <= n

解:

解题思路:

树区别与图的特点是:没有环(不论是对于有向边还是无向边)

有根树的特点:

  • 只有唯一的一个入度为 00 的结点,它是根结点;
  • 不是根结点的其它所有的结点入度为 11;
  • 不可能存在入度为 22 的结点。

在这里插入图片描述

AC代码:

class Solution {
    int N = 1005;
    int[] parent = new int[N];
    // 1.有入度为2(删边检查树) 2.没有入度为2(检测环)
    public int[] findRedundantDirectedConnection(int[][] edges) {
        // 1.入度统计
        int len = edges.length;
        int[] inDegree = new int[N];
        for(int i = 0; i < len; ++ i) {
            inDegree[edges[i][1]] ++;
        }
        // 2.找入度为2的点,优先要后边的节点,倒序遍历
        List<Integer> twoDegree = new ArrayList<>();
        for(int i = len - 1; i >= 0; -- i) {
            if(inDegree[edges[i][1]] == 2) {
                twoDegree.add(i);
            }
        }
        // 存在入度为2的点,一定是两条边删一条
        if(!twoDegree.isEmpty()) {
            if(isTreeAfterRemoveEdge(edges, twoDegree.get(0))) {
                return edges[twoDegree.get(0)];
            }
            return edges[twoDegree.get(1)];
        }
        return getRemoveEdge(edges);
    }
    // 删除一条边后看是不是树
    boolean isTreeAfterRemoveEdge(int[][] edges, int deleteEdge) {
        init();
        for(int i = 0; i < edges.length; ++ i) {
            if(i == deleteEdge) continue;
            if(find(edges[i][0]) == find(edges[i][1])) { // 构成有向环
                return false;
            }
            join(edges[i][0], edges[i][1]);
        }
        return true;    
    }
    // 在有向图里找到要删除的边,使其变成树
    int[] getRemoveEdge(int[][] edges) {
        init();
        for(int i = 0; i < edges.length; ++ i) {
            if(find(edges[i][0]) == find(edges[i][1])) {
                return edges[i];
            }
            join(edges[i][0], edges[i][1]);
        }
        return new int[] {};
    }
    // 初始化并查集
    void init() {
        for(int i = 0; i < N; ++ i) {
            parent[i] = i;
        }
    }
    // 并查集寻根
    int find(int u) {
        if(u == parent[u]) {
            return u;
        }
        parent[u] = find(parent[u]);
        return parent[u];
    }
    // 将 v -> u 加入并查集
    void join(int u, int v) {
        u = find(u);
        v = find(v);
        if(u == v) return;
        parent[v] = u; 
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:30:41  更:2022-06-06 17:31:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:03:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码