LeetCode 2092. 找出知晓秘密的所有专家

Posted 英雄哪里出来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 2092. 找出知晓秘密的所有专家相关的知识,希望对你有一定的参考价值。

文章目录

一、题目

1、题目描述

  给你一个整数 n n n ,表示有 n n n 个专家从 0 0 0 n − 1 n - 1 n1 编号。另外给你一个下标从 0 0 0 开始的二维整数数组 meetings,其中meetings[i] = [xi, yi, timei]表示专家 xi和专家 yi在时间 timei要开一场会。一个专家可以同时参加多场会议 。最后,给你一个整数 firstPerson
  专家 0 有一个 秘密 ,最初,他在时间 0将这个秘密分享给了专家 firstPerson。接着,这个秘密会在每次有知晓这个秘密的专家参加会议时进行传播。更正式的表达是,每次会议,如果专家 xi在时间 timei时知晓这个秘密,那么他将会与专家 yi分享这个秘密,反之亦然。
  秘密共享是 瞬时发生 的。也就是说,在同一时间,一个专家不光可以接收到秘密,还能在其他会议上与其他专家分享。
  在所有会议都结束之后,返回所有知晓这个秘密的专家列表。你可以按 任何顺序 返回答案。
  样例输入: n = 6, meetings = [[1,2,5],[2,3,8],[1,5,10]], firstPerson = 1
  样例输出: [0,1,2,3,5]

2、基础框架

  • C++ 版本给出的基础框架代码如下:
class Solution 
public:
    vector<int> findAllPeople(int n, vector<vector<int>>& meetings, int firstPerson) 
        
    
;

3、原题链接

LeetCode 2092. 找出知晓秘密的所有专家

二、解题报告

1、思路分析

   ( 1 ) (1) (1) 首先,把 0 和 firstPerson放到同一个集合。
   ( 2 ) (2) (2) 然后,将所有的会议按照时间单调不降排序。
   ( 3 ) (3) (3) 接着,枚举每个会议 ( x i , y i ) (x_i, y_i) (xi,yi),如果 x i x_i xi 和 0 在同一个集合的话,则把 y i y_i yi 和 0 放到同一个集合中,反之亦然。
   ( 4 ) (4) (4) 这时候,我们需要考虑一种情况:就是时间相同的时候,不同的枚举顺序会带来不同的结果,所以我们需要把所有相同时间内的会议先组织成一个网络连通图进行染色。
   ( 5 ) (5) (5) 具体的,对于所有时间相同的情况,建立 ( x i , y i ) (x_i, y_i) (xi,yi) 的双向边,然后走一次 f l o o d f i l l floodfill floodfill,将染色相同元素进行合并,然后再用 ( 3 ) (3) (3) 的方法进行判断从而合并集合。

2、时间复杂度

   最坏时间复杂度 O ( n ) O(n) O(n)

3、代码详解

#define maxn 100005

int head[maxn], edgeCnt;
int q[maxn], front, rear;
int fuck[maxn], color[maxn];
struct Edge 
    int v;
    int next;
E[maxn*2];

class Solution 

    void add(int u, int v) 
        Edge &e = E[edgeCnt];
        e.v = v;
        e.next = head[u];
        head[u] = edgeCnt++;
    

    void clearEdges(vector<vector<int>>& sm, int l, int r) 
        for(int i = l; i <= r; ++i) 
            int u = sm[i][0];
            int v = sm[i][1];
            head[u] = head[v] = -1;
            color[u] = color[v] = -1;
        
        edgeCnt = 0;
    

    void constructEdges(vector<vector<int>>& sm, int l, int r) 
        clearEdges(sm, l, r);
        
        for(int i = l; i <= r; ++i) 
            int u = sm[i][0];
            int v = sm[i][1];
            add(u, v);
            add(v, u);
        
    

    void ranse(int u) 
        if(!color[u]) 
            return ;
        
        color[u] = 0;
        fuck[u] = 0;

        for(int e = head[u]; ~e; e = E[e].next ) 
            ranse(E[e].v);
        
    


    void slove(vector<vector<int>>& sm, int l, int r) 
        constructEdges(sm, l, r);

        int i, j;
        for(i = l; i <= r; ++i) 
            int u = sm[i][0];
            int v = sm[i][1];

            if(!fuck[u] && color[u] == -1) 
                ranse(u);
            
            else if(!fuck[v] && color[v] == -1) 
                ranse(v);
            
        

        clearEdges(sm, l, r);
    

public:
    vector<int> findAllPeople(int n, vector<vector<int>>& meetings, int firstPerson) 
        edgeCnt = 0;
        memset(head, -1, sizeof(head));
        memset(fuck, -1, sizeof(fuck));
        memset(color, -1, sizeof(color));

        vector <int> ans;
        fuck[ firstPerson ] = fuck[0] = 0;

        sort(meetings.begin(), meetings.end(), [=](vector<int>&a, vector<int>&b) -> bool  return a[2] < b[2]; );

        int m = meetings.size();
        int i, j;
        for(i = 0; i < m; ++i) 
            for(j = i; j < m; ++j) 
                if(meetings[j][2] != meetings[i][2]) 
                    break;
                
            
            slove(meetings, i, j - 1);
            i = j - 1;    // 我嘞个去!!!!!! 写成 j = i - 1
        


        for(i = 0; i < n; ++i) 
            if(!fuck[i])
                ans.push_back(i);
        
        return ans;
    
;

三、本题小知识

  建边的时候可以采用链式前向星,会比vector快很多。


四、加群须知

  相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」
  那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:

🌌《算法入门指引》🌌

  如果链接被屏蔽,或者有权限问题,可以私聊作者解决。

  大致题集一览:













  为了让这件事情变得有趣,以及「 照顾初学者 」,目前题目只开放最简单的算法 「 枚举系列 」 (包括:线性枚举、双指针、前缀和、二分枚举、三分枚举),当有 一半成员刷完 「 枚举系列 」 的所有题以后,会开放下个章节,等这套题全部刷完,你还在群里,那么你就会成为「 夜深人静写算法 」专家团 的一员。
  不要小看这个专家团,三年之后,你将会是别人 望尘莫及 的存在。如果要加入,可以联系我,考虑到大家都是学生, 没有「 主要经济来源 」,在你成为神的路上,「 不会索取任何 」
  🔥联系作者,或者扫作者主页二维码加群,加入刷题行列吧🔥


🔥让天下没有难学的算法🔥

C语言免费动漫教程,和我一起打卡!
🌞《光天化日学C语言》🌞

让你养成九天持续刷题的习惯
🔥《九日集训》🔥

入门级C语言真题汇总
🧡《C语言入门100例》🧡

组团学习,抱团生长
🌌《算法零基础100讲》🌌

几张动图学会一种数据结构
🌳《画解数据结构》🌳

竞赛选手金典图文教程
💜《夜深人静写算法》💜

以上是关于LeetCode 2092. 找出知晓秘密的所有专家的主要内容,如果未能解决你的问题,请参考以下文章

杭电2092

leetcode 双周赛9 找出所有行中最小公共元素

设计模式小秘密

LeetCode刷题1863-简单-找出所有子集的异或和

LeetCode刷题1863-简单-找出所有子集的异或和

Leetcode5759. 找出所有子集的异或总和再求和(二进制模拟暴搜)