THN Interview Prep

323. Number of Connected Components in an Undirected Graph

At a Glance

  • Topic: graphs
  • Pattern: Union-Find or DFS/BFS
  • Difficulty: Medium
  • Companies: Amazon, Google, Microsoft, Meta, Apple
  • Frequency: Medium
  • LeetCode: 323 (Premium)

Problem (one-liner)

Given n nodes 0..n-1 and a list of undirected edges, return the number of connected components.

Recognition Cues

  • Static connectivity count
  • Undirected edges — Union-Find merge or DFS flood

Diagram

At-a-glance flow (replace with problem-specific Mermaid as you refine this note). camelCase node IDs; no spaces in IDs.

Loading diagram…

Approaches

  • Adjacency + DFSO(n+e) time, O(n+e) space.
  • Union-FindO(n α(n)) — compact for edge-list input.

Optimal Solution

Go

type unionFind struct {
	parent []int
}

func newUnionFind(size int) *unionFind {
	parent := make([]int, size)
	for index := range parent {
		parent[index] = index
	}
	return &unionFind{parent: parent}
}

func (finder *unionFind) find(node int) int {
	if finder.parent[node] != node {
		finder.parent[node] = finder.find(finder.parent[node])
	}
	return finder.parent[node]
}

func (finder *unionFind) union(left int, right int) {
	rootLeft := finder.find(left)
	rootRight := finder.find(right)
	if rootLeft != rootRight {
		finder.parent[rootRight] = rootLeft
	}
}

func countComponents(nodeCount int, edges [][]int) int {
	finder := newUnionFind(nodeCount)
	for _, edge := range edges {
		finder.union(edge[0], edge[1])
	}
	roots := map[int]struct{}{}
	for node := 0; node < nodeCount; node++ {
		roots[finder.find(node)] = struct{}{}
	}
	return len(roots)
}

JavaScript

class UnionFind {
  constructor(size) {
    this.parent = Array.from({ length: size }, (_, index) => index);
  }

  find(node) {
    if (this.parent[node] !== node) {
      this.parent[node] = this.find(this.parent[node]);
    }
    return this.parent[node];
  }

  union(left, right) {
    const rootLeft = this.find(left);
    const rootRight = this.find(right);
    if (rootLeft !== rootRight) {
      this.parent[rootRight] = rootLeft;
    }
  }
}

function countComponents(nodeCount, edges) {
  const finder = new UnionFind(nodeCount);
  for (const edge of edges) {
    finder.union(edge[0], edge[1]);
  }
  const roots = new Set();
  for (let node = 0; node < nodeCount; node += 1) {
    roots.add(finder.find(node));
  }
  return roots.size;
}

Walkthrough

Union each edge; distinct find roots after processing equals component count.

Invariant: DSU maintains partition of nodes into connected components.

Edge Cases

  • No edges — n isolated nodes
  • Complete connection — one component

Pitfalls

  • Counting edges instead of unique roots

Similar Problems

Variants

  • Dynamic edges (online) — still DSU

Mind-Map Tags

#union-find #components #undirected #connectivity

Last updated on

Spotted something unclear or wrong on this page?

On this page