前言:

这是力扣的一道算法题,采用按时间分组 + 图的连通性传播DFS

这是一种 事件驱动 + 图遍历 的混合策略,核心思想是:

秘密只能在「同一时刻」通过「会议网络」传播;不同时间的会议不能互相影响。

理解起来挺简单的,就是分组,然后遍历。


题目:

给你一个整数 n ,表示有 n 个专家从 0 到 n - 1 编号。另外给你一个下标从 0 开始的二维整数数组 meetings ,其中 meetings[i] = [xi, yi, timei] 表示专家 xi 和专家 yi 在时间 timei 要开一场会。一个专家可以同时参加 多场会议 。最后,给你一个整数 firstPerson 。

专家 0 有一个 秘密 ,最初,他在时间 0 将这个秘密分享给了专家 firstPerson 。接着,这个秘密会在每次有知晓这个秘密的专家参加会议时进行传播。更正式的表达是,每次会议,如果专家 xi 在时间 timei 时知晓这个秘密,那么他将会与专家 yi 分享这个秘密,反之亦然。

秘密共享是 瞬时发生 的。也就是说,在同一时间,一个专家不光可以接收到秘密,还能在其他会议上与其他专家分享。

在所有会议都结束之后,返回所有知晓这个秘密的专家列表。你可以按 任何顺序 返回答案。

示例 1:

输入:n = 6, meetings = [[1,2,5],[2,3,8],[1,5,10]], firstPerson = 1
输出:[0,1,2,3,5]
解释:
时间 0 ,专家 0 将秘密与专家 1 共享。
时间 5 ,专家 1 将秘密与专家 2 共享。
时间 8 ,专家 2 将秘密与专家 3 共享。
时间 10 ,专家 1 将秘密与专家 5 共享。
因此,在所有会议结束后,专家 0、1、2、3 和 5 都将知晓这个秘密。

示例 2:

输入:n = 4, meetings = [[3,1,3],[1,2,2],[0,3,3]], firstPerson = 3
输出:[0,1,3]
解释:
时间 0 ,专家 0 将秘密与专家 3 共享。
时间 2 ,专家 1 与专家 2 都不知晓这个秘密。
时间 3 ,专家 3 将秘密与专家 0 和专家 1 共享。
因此,在所有会议结束后,专家 0、1 和 3 都将知晓这个秘密。

示例 3:

输入:n = 5, meetings = [[3,4,2],[1,2,1],[2,3,1]], firstPerson = 1
输出:[0,1,2,3,4]
解释:
时间 0 ,专家 0 将秘密与专家 1 共享。
时间 1 ,专家 1 将秘密与专家 2 共享,专家 2 将秘密与专家 3 共享。
注意,专家 2 可以在收到秘密的同一时间分享此秘密。
时间 2 ,专家 3 将秘密与专家 4 共享。
因此,在所有会议结束后,专家 0、1、2、3 和 4 都将知晓这个秘密。

提示:

  • 2 <= n <= 105
  • 1 <= meetings.length <= 105
  • meetings[i].length == 3
  • 0 <= xi, yi <= n - 1
  • xi != yi
  • 1 <= timei <= 105
  • 1 <= firstPerson <= n - 1

题目讲解:

本题要求找出所有最终知晓秘密的专家。

初始时,专家 0 和 firstPerson 知道秘密,秘密仅在会议中传播,且同一时间点内所有连通的专家构成信息共享组——只要组内一人知密,全员即刻获知。

关键在于:秘密传播具有严格的时间顺序,不同时间的会议不能跨时段影响。

因此,需先将会议按时间排序,再逐时间点构建无向图,通过 DFS  从已知秘密者出发,标记其所在连通分量的所有成员。

该方法高效利用了图的连通性与事件驱动思想,确保传播逻辑正确且时间复杂度可控。


代码:

class Solution {
    public List<Integer> findAllPeople(int n, int[][] meetings, int firstPerson) {
        Arrays.sort(meetings,(a,b) -> a[2] - b[2]);

        Set<Integer> havaSecret = new HashSet<>();
        havaSecret.add(0);
        havaSecret.add(firstPerson);

        int m = meetings.length;
        for(int i = 0;i<m;){
            Map<Integer,List<Integer>> g = new HashMap<>();
            int time = meetings[i][2];
            for(;i<m && meetings[i][2] == time;i++){
                int x = meetings[i][0];
                int y = meetings[i][1];
                g.computeIfAbsent(x,k -> new ArrayList<>()).add(y);
                g.computeIfAbsent(y,k -> new ArrayList<>()).add(x);
            }

            Set<Integer> vis = new HashSet<>();
            for(int x:g.keySet()){
                if(havaSecret.contains(x) && !vis.contains(x)){
                    dfs(x,g,vis,havaSecret);
                }
            }
        }
        return new ArrayList<>(havaSecret);
    }

    private void dfs(int x,Map<Integer,List<Integer>> g,Set<Integer> vis,Set<Integer> havaSecret){
        vis.add(x);
        havaSecret.add(x);
        for(int y : g.get(x)){
            if(!vis.contains(y)){
                dfs(y,g,vis,havaSecret);
            }
        }
    }
}

代码讲解:

一、初始化

先对二维整数数组meetings,其中meetings进行排序,使用Lambda表达式,对时间排序

建立Hashset,不予许有重复的元素

一开始专家0和专家firstperpon知道秘密,所以需要初始化加入

Arrays.sort(meetings,(a,b) -> a[2] - b[2]);
Set<Integer> havaSecret = new HashSet<>();
havaSecret.add(0);
havaSecret.add(firstPerson);

二、逻辑实现

先初始化一个散列表,键值对,在嵌套一个list,做一个无向图,表示该时间内有哪些专家在开会,可以互相知晓秘密,然后互相添加到对方的邻接表中

然后是同一个通量中,只要有一个人知道秘密了,其他人就肯定知道秘密

 int m = meetings.length;
 for(int i = 0;i<m;){
    Map<Integer,List<Integer>> g = new HashMap<>();
    int time = meetings[i][2];
    for(;i<m && meetings[i][2] == time;i++){
        int x = meetings[i][0];
        int y = meetings[i][1];
        g.computeIfAbsent(x,k -> new ArrayList<>()).add(y);
        g.computeIfAbsent(y,k -> new ArrayList<>()).add(x);
   }
   Set<Integer> vis = new HashSet<>();
   for(int x:g.keySet()){
       if(havaSecret.contains(x) && !vis.contains(x)){
           dfs(x,g,vis,havaSecret);
       }
    }

三、递归

把知道的加入,不知道的继续遍历,递归

private void dfs(int x,Map<Integer,List<Integer>> g,Set<Integer> vis,Set<Integer> havaSecret){
    vis.add(x);
    havaSecret.add(x);
    for(int y : g.get(x)){
        if(!vis.contains(y)){
            dfs(y,g,vis,havaSecret);
        }
    }

结语:

希望这篇博客可以帮助大家理解,一起加油!每天进步一点点!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐