2092. Find All People With Secret - Explanation

Problem Link



class Solution:
    def findAllPeople(self, n: int, meetings: list[list[int]], firstPerson: int) -> list[int]:
        secrets = set([0, firstPerson])  # People with secret
        time_map = {}  # time -> adjacency list meetings

        for src, dst, t in meetings:
            if t not in time_map:
                time_map[t] = defaultdict(list)
            time_map[t][src].append(dst)
            time_map[t][dst].append(src)

        def dfs(src, adj):
            if src in visit:
                return
            visit.add(src)
            secrets.add(src)
            for nei in adj[src]:
                dfs(nei, adj)

        for t in sorted(time_map.keys()):
            visit = set()
            for src in time_map[t]:
                if src in secrets:
                    dfs(src, time_map[t])

        return list(secrets)

Time & Space Complexity

  • Time complexity: O(mlogm+n)O(m \log m + n)
  • Space complexity: O(m+n)O(m + n)

Where mm is the number of meetings and nn is the number of people.


class Solution:
    def findAllPeople(self, n: int, meetings: list[list[int]], firstPerson: int) -> list[int]:
        secrets = set([0, firstPerson])  # People with secret
        time_map = {}  # time -> adjacency list meetings

        for src, dst, t in meetings:
            if t not in time_map:
                time_map[t] = defaultdict(list)
            time_map[t][src].append(dst)
            time_map[t][dst].append(src)

        for t in sorted(time_map.keys()):
            visit = set()
            q = deque()

            for src in time_map[t]:
                if src in secrets:
                    q.append(src)
                    visit.add(src)

            while q:
                node = q.popleft()
                secrets.add(node)
                for nei in time_map[t][node]:
                    if nei not in visit:
                        visit.add(nei)
                        q.append(nei)

        return list(secrets)

Time & Space Complexity

  • Time complexity: O(mlogm+n)O(m \log m + n)
  • Space complexity: O(m+n)O(m + n)

Where mm is the number of meetings and nn is the number of people.


3. Iterative DFS

class Solution:
    def findAllPeople(self, n: int, meetings: list[list[int]], firstPerson: int) -> list[int]:
        meetings.sort(key=lambda x: x[2])  # Sort by time
        secrets = [False] * n
        secrets[0] = secrets[firstPerson] = True

        for _, group in groupby(meetings, key=lambda x: x[2]):
            adj = defaultdict(list)
            visited = set()

            for u, v, _ in group:
                adj[u].append(v)
                adj[v].append(u)
                if secrets[u]:
                    visited.add(u)
                if secrets[v]:
                    visited.add(v)

            stack = list(visited)
            while stack:
                node = stack.pop()
                for nei in adj[node]:
                    if nei not in visited:
                        visited.add(nei)
                        stack.append(nei)
                        secrets[nei] = True

        return [i for i in range(n) if secrets[i]]

Time & Space Complexity

  • Time complexity: O(mlogm+n)O(m \log m + n)
  • Space complexity: O(m+n)O(m + n)

Where mm is the number of meetings and nn is the number of people.


4. Disjoint Set Union

class DSU:
    def __init__(self, n):
        self.Parent = list(range(n + 1))
        self.Size = [1] * (n + 1)

    def find(self, node):
        if self.Parent[node] != node:
            self.Parent[node] = self.find(self.Parent[node])
        return self.Parent[node]

    def union(self, u, v):
        pu, pv = self.find(u), self.find(v)
        if pu == pv:
            return False
        if self.Size[pu] < self.Size[pv]:
            pu, pv = pv, pu
        self.Size[pu] += self.Size[pv]
        self.Parent[pv] = pu
        return True

    def reset(self, node):
        self.Parent[node] = node
        self.Size[node] = 1

class Solution:
    def findAllPeople(self, n: int, meetings: list[list[int]], firstPerson: int) -> list[int]:
        meetings.sort(key=lambda x: x[2])  # Sort by time
        dsu = DSU(n)
        dsu.union(0, firstPerson)

        for _, group in groupby(meetings, key=lambda x: x[2]):
            group_nodes = set()
            for u, v, _ in group:
                dsu.union(u, v)
                group_nodes.add(u)
                group_nodes.add(v)

            for node in group_nodes:
                if dsu.find(node) != dsu.find(0):
                    dsu.reset(node)

        return [i for i in range(n) if dsu.find(i) == dsu.find(0)]

Time & Space Complexity

  • Time complexity: O(mlogm+(mα(n)))O(m \log m + (m * α(n)))
  • Space complexity:
    • O(n)O(n) extra space.
    • O(m)O(m) space depending on the sorting algorithm.

Where mm is the number of meetings and nn is the number of people.