Find All People With Secret

HardDepth-First SearchBreadth-First SearchUnion FindGraphSorting

Solution

class UnionFind {
  private readonly parents: number[];
 
  constructor(n: number) {
    this.parents = Array.from({ length: n }, (_, i) => i);
  }
 
  public find(x: number): number {
    if (this.parents[x] === x) {
      return x;
    }
    this.parents[x] = this.find(this.parents[x]);
    return this.parents[x];
  }
 
  public union(x: number, y: number): void {
    const rootX = this.find(x);
    const rootY = this.find(y);
    if (rootX === rootY) {
      return;
    }
    if (rootX < rootY) {
      this.parents[rootY] = rootX;
    } else {
      this.parents[rootX] = rootY;
    }
  }
 
  public reset(x: number): void {
    this.parents[x] = x;
  }
 
  public isConnected(x: number, y: number): boolean {
    return this.find(x) === this.find(y);
  }
}
 
export function findAllPeople(n: number, meetings: number[][], firstPerson: number): number[] {
  meetings.sort((a, b) => a[2] - b[2]);
 
  const unionFind = new UnionFind(n);
  unionFind.union(0, firstPerson);
 
  let currentIndex = 0;
  const m = meetings.length;
  const pool = new Set<number>();
  while (currentIndex < m) {
    const currentTime = meetings[currentIndex][2];
    while (currentIndex < m && currentTime === meetings[currentIndex][2]) {
      const [x, y] = meetings[currentIndex];
      unionFind.union(x, y);
      pool.add(x);
      pool.add(y);
      currentIndex += 1;
    }
    for (const person of pool) {
      if (!unionFind.isConnected(0, person)) {
        unionFind.reset(person);
      }
    }
    pool.clear();
  }
 
  const answer: number[] = [];
  for (let person = 0; person < n; person++) {
    if (unionFind.isConnected(0, person)) {
      answer.push(person);
    }
  }
  return answer;
}