力扣——并查集算法系列

news2024/11/19 2:45:32
【LeetCode 684. 冗余连接】

在这里插入图片描述

在这里插入图片描述

思路:

首先因为这是一个无向图,所以不需要考虑谁是树根。

那么我们一条条边加入到图里去,直到出现了环为止,那么这条边就是冲突的边,需要删除掉。

那么怎么判断是否出现了环呢?如果加入一条边 [u , v] 的时候,两个结点所在的连通块不是同一个,那么一定没有环。否则的话,两个结点连在了同一棵子树上,那么一定会产生一个环。

如何高效的判断两个结点是否在同一棵子树上呢?这就需要用到一个数据结构——并查集

并查集采用一个数组 f[i] 来表示结点 i 的父结点。那么初始的时候没有任何边,定义所有结点的父结点等于它自身:f[i] = i 。

当加入一条边 [u , v] 的时候,可以沿着 u -> f[u] ->f[f[u]] -> … 的路径递归找到 u 所在子树的根结点 ru( v 同理得到 rv ),然后只需要判断两个根结点是否相同就行了。如果根结点相同,那么就产生环了,直接输出这个冲突边就行。否则的话就要把这两棵子树连到一起,最简单的做法就是直接把 ru 连到 rv 下面,当作它的子结点,那么就需要更新 f[ru] = rv 。

下面讲两个常用的并查集优化。

路径压缩: 因为我们无需关注每一棵子树结构是什么样的,我们只关注它的根结点是谁。所以为了减小查找根结点的时间,每个结点离根结点要尽量近。

那么我们定义查找根结点函数 find(u) ,如果 u = f[u] ,那么不用找了,它自己就是根结点。否则的话调用 find(f[u]) 递归寻找子树的根结点。最后做一步路径压缩的优化,把根结点当作 u 的父结点: f[u] = find(f[u]) 。这样下次再查找的时候,路径长度就变为了 1 ,一步就能找到根结点了。

按秩合并: 合并两棵子树的时候,为了使得合并后的子树高度尽量小,需要把高度小的那棵子树接在高度高的那棵下面,当作儿子。

所以定义一个 rank[i] 数组,用来记录 i 这个结点作为根结点的子树高度,初始时全都是 1 。那么在合并的时候,把 rank 值小的接到大的下面去,如果一样怎么办呢?随便接,然后把合并后的根结点 rank 值加 1 就行了。

代码实现:

申请两个全局数组记录父节点和树高;

static const int N = 1010;
int f[N], rank[N];

主函数;

vector<int> findRedundantConnection(vector<vector<int>>& edges) {
    init();
    for (auto e : edges) {
        int u = e[0], v = e[1];
        if (same(u, v)) return {u, v};
        else join(u, v);
    }
    return {-1, -1};
}

初始化每个节点为一棵新的树;

    void init() {
        for (int i = 0; i < N; ++i) {
            f[i] = i;
            rank[i] = 1;
        }
    }

寻找父节点的功能函数;

    int find(int u) {
        return u==f[u] ? u : f[u]=find(f[u]);
    }

合并树;

void join(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return;
    if (rank[u] < rank[v]) {
        f[u] = v;
    } else {
        f[v] = u;
        if (rank[u] == rank[v]) {
            rank[u]++;
        }
    }
}

判断输入的节点对中的两个节点是否属于同一个根节点;

bool same(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

提交总览:
在这里插入图片描述

至此,本题结束。

【LeetCode 685. 冗余连接 II】

在这里插入图片描述

在这里插入图片描述

思路:

这题是上一道题 684. 冗余连接 - 力扣(LeetCode)的进阶版,区别就是无向图变成了有向图。

上一道题解说过,无向图能构成一棵树的条件是没有环,那么有向图的条件是什么呢?

首先还是得没有环,其次因为是边是有向的,所以一个结点只能有一个父结点(也就是入度为 1 )。那么这题解法就有了。

  • 首先判断有没有入度为 2 的结点,如果有的话,那两条边一定有一条得删掉。
  • 按照出现时间从后到前看那两条边,删掉其中一条之后是否能构成一棵树(也就是无环)。如果删掉了无环,那就直接返回这条边作为答案。
  • 如果入度全是 1 ,那就直接按照出现时间从前到后看添加了哪一条边之后开始出现了环,那么那条边就是答案。

判断能否构成一棵树的话还是用并查集,唯一区别就是不需要用按秩合并的优化了,而且给定有向边 [u , v],只能把 v 接在 u 下面。

代码实现:

申请记录父节点和入度;

    static const int N = 1010;
    int f[N], degree[N];
    int n;

主函数;

vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
    n = edges.size();
    memset(degree, 0, sizeof degree);
    for (auto e : edges) ++degree[e[1]];
    for (int i = n-1; i >= 0; --i) {
        if (degree[edges[i][1]] == 2 && !wrongEdge(edges, i).size()) {
            return edges[i];
        }
    }
    return wrongEdge(edges, n);
}

判断是否无环的功能函数;

    vector<int> wrongEdge(vector<vector<int>>& edges, int except) {
        init();
        for (int i = 0; i < n; ++i) {
            if (i == except) continue;
            int u = edges[i][0], v = edges[i][1];
            if (same(u, v)) return edges[i];
            join(u, v);
        }
        return {};
    }

同上题功能相似的四个基础的功能函数,注意这里是有向图,所以 join 函数写法不同;

void init() {
    for (int i = 1; i <= n; ++i) {
        f[i] = i;
    }
}

int find(int u) {
    return u==f[u] ? u : f[u]=find(f[u]);
}

void join(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return;
    f[v] = u;
}

bool same(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

提交总览:
在这里插入图片描述

至此,本题结束。

并查集算法系列到此结束!!

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

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

相关文章

36. 【Android教程】侧滑菜单:DrawerLayout

侧滑菜单是用来在页面上增加一个抽屉式菜单栏的控件&#xff0c;它一般位于左侧&#xff0c;用户可以通过侧滑拉出或者关闭。通常你可以放置一些菜单项或者上下文相关的设置在里面&#xff0c;帮助你节省屏幕空间同时可以很方便的随时打开。侧滑菜单其实就是下面这货&#xff1…

python 对图片进行操作

Pillow是一个强大的图像处理库&#xff0c;它提供了许多用于打开、操作和保存图像的功能。 Image模块&#xff1a; Image模块提供了用于打开、创建、编辑和保存图像的基本功能。可以使用Image.open()函数来打开图像文件&#xff0c;或者使用Image.new()函数来创建新的图像,还可…

【Java框架】Spring框架(六)——Spring中的Bean的作用域

目录 Bean的作用域1.singleton(默认)代码示例 2.prototype代码示例 3.request代码示例 4.session代码示例 5.application代码示例 websocket Bean的作用域 Spring支持6个作用域&#xff1a;singleton、prototype、request、session、application、websocket 1.singleton(默认…

山与路远程控制 一个基于electron和golang实现的远控软件

山与路远程控制 &#x1f3a5;项目演示地址 还在制作… ♻️项目基本介绍 山与路远程控制是基于electron(vue3)和golang实现的远程控制软件(项目界面主要模仿向日葵远程软件,如有侵权请告知),代码可能有点臃肿毕竟只花了一周左右写的无聊项目,如果对其感兴趣的大佬可以fork自…

【信号处理】心电信号传统R波检测定位典型方法实现(matlab)

关于 心电信号中QRS波检测是一个非常重要的步骤&#xff0c;可以用于实现重要波群的基本定位&#xff0c;在定位基础上&#xff0c;可以进一步分析心电信号的特征变化&#xff0c;从而为医疗诊断提供必要的参考。 工具 MATLAB ECG心电信号 方法实现 ECG心电信号加载 ecg …

Java中的数组(上)

1.怎样定义Java中的数组 package day40; ​ public class day25 {public static void main(String[] args) {int[] array1{1,2,3,4,5};int[] array2new int[10];for (int i 0; i < array1.length; i) {System.out.print(array1[i]" ");}System.out.println();fo…

学习笔记:Vue2中级篇

Vue2 学习笔记&#xff1a;Vue2基础篇_ljtxy.love的博客-CSDN博客学习笔记&#xff1a;Vue2中级篇_ljtxy.love的博客-CSDN博客学习笔记&#xff1a;Vue2高级篇_ljtxy.love的博客-CSDN博客 Vue3 学习笔记&#xff1a;Vue3_ljtxy.love的博客&#xff09;-CSDN博客 文章目录 5.…

HTTP 方法和使用场景大全

本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 HTTP 方法和使用场景大全 HTTP&#xff08;超文本传输协议&#xff09;方法&#xff0c;也称为 HTTP 动词&#xff0c;定义了可以对资源执行的操作。理解这些方法的使用对于 Web 开发至…

【分治】Leetcode 排序数组

题目讲解 912. 排序数组 算法讲解 我们这里使用三指针&#xff0c;将数组分成三块&#xff1a;<key 和 key 和 >key,如果当前指针指向的数字<key&#xff0c;我们就swap(nums[left]), nums[i] 。如果当前的数字key &#xff0c;就让i。如果当前的数字>key&…

MySQL基础篇总结

参考&#xff1a;黑马程序员MySQL基础视频链接 数据库基本操作 启动与停止 1.第一种方式&#xff1a; 1>以管理员身份运行cmd 2>在命令行窗口中输入: 启动:net start mysql80停止:net stop mysql80 2.第二种方式: 1>WinR快捷方式打开如下&#xff1a; 输入&#…

【探索Linux】P.32(自定义协议)

阅读导航 引言一、自定义协议概念二、自定义协议需要注意的事项三、自定义协议示例(跨网络计算器协议)✅协议代码&#xff08;Protocol.hpp&#xff09;1. 计算器协议简单介绍2. 序列化部分3. 反序列化部分4. 请求和响应数据结构5. 使用自定义协议 四、总结温馨提示 引言 在上…

第三届 SWCTF-Web 部分 WP

写在前面 题目主要涉及的是前端 php 内容知识&#xff0c;仅以本篇博客记录自己 Web 出题的奇思妙想。 Copyright © [2024] [Myon⁶]. All rights reserved. 目录 1、HTTP 2、再见了晚星 3、myon123_easy_php 4、baby_P0P 5、LOGIN!!! 1、HTTP 首页文件默认就是 ind…

BTP连接cloud connector中配置的SAP

登录地址 登录之后可以看到我们已经配置成功的后端系统SAP。 从cloud connector中获取location ID ,然后在BTP中配置Destination 选择目标标签页&#xff0c;点击‘新建目标’&#xff0c;如下图&#xff1a; 新建连接 暂时不知道错误原因 创建目标-HTTP  新建目标&…

Leetcode 第 394 场周赛

Leetcode 第 394 场周赛 1. [统计特殊字母的数量 I](https://leetcode.cn/problems/count-the-number-of-special-characters-i/)2. [统计特殊字母的数量 II](https://leetcode.cn/problems/count-the-number-of-special-characters-ii/)3. [使矩阵满足条件的最少操作次数](htt…

大一考核题解

在本篇中&#xff0c;将尽力使用多种解法&#xff0c;来达到一题多练的效果。 1&#xff1a; 1.原题链接&#xff1a; 238. 除自身以外数组的乘积 - 力扣&#xff08;LeetCode&#xff09; 这道题首先一眼肯定想到拿整体的积除以当前元素&#xff0c;将结果作为ans&#xff0c;…

护眼台灯哪个牌子最好?盘点五款目前比较好用的护眼台灯

护眼台灯哪个牌子好&#xff1f;护眼台灯比较好的牌子有书客、雷士、爱德华医生等。这些护眼台灯得益于强大的研发实力&#xff0c;不仅具备基础的照明功能&#xff0c;更在护眼效果上表现卓越。它们能够真正起到保护眼睛的作用&#xff0c;有效缓解眼部疲劳&#xff0c;为阅读…

Unity3D 羊了个羊等游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

怎样快速打造二级分销小程序

乔拓云是一个专门开发小程序模板的平台&#xff0c;致力于帮助商家快速上线自己的小程序。通过套用乔拓云提供的精美模板&#xff0c;商家无需具备专业的技术背景&#xff0c;也能轻松打造出功能齐全、美观大方的小程序。 在乔拓云的官网&#xff0c;商家可以免费注册账号并登录…

【批量区域识别内容重命名】批量识别图片区域文字并重命名,批量图片部分识别内容重命文件,PDF区域识别提取重命名

我们在工作和生活中经常遇到这样的需求&#xff1a;比如将以下的图片区域识别进行重命名&#xff0c;批量识别后改成以时间和工作内容重命名&#xff0c;便于日后检索&#xff0c;快速查询 首先我们拍摄照片用到的是水印相机&#xff0c;这里的文字呢我们需要加个背景&#xff…

[数字人]唇形驱动,不生成头部动作算法总结

安全验证 - 知乎知乎&#xff0c;中文互联网高质量的问答社区和创作者聚集的原创内容平台&#xff0c;于 2011 年 1 月正式上线&#xff0c;以「让人们更好的分享知识、经验和见解&#xff0c;找到自己的解答」为品牌使命。知乎凭借认真、专业、友善的社区氛围、独特的产品机制…