8 min

Union-Find (Disjoint Set)

Estrutura de dados para rastrear elementos particionados em conjuntos disjuntos, com operações quase O(1) para unir conjuntos e verificar conectividade.

DifícilO(alpha(n)) / O(n)Estrutura de DadosConjuntosConectividadeKruskal

Visualizador Interativo

Union-FindPasso 1 / 38
Raiz: Alice
Alir:0
Raiz: Bob
Bobr:0
Raiz: Carol
Carr:0
Raiz: David
Davr:0
Raiz: Eve
Ever:0
Raiz: Frank
Frar:0
Array Parent
Alic->Alic
Bob->Bob
Caro->Caro
Davi->Davi
Eve->Eve
Fran->Fran
Velocidade:800ms
Historico de Passos
#0Inicializando Union-Find: cada elemento e seu proprio pai

Como Funciona

Union-Find (ou Disjoint Set Union - DSU) é uma estrutura de dados que mantém uma coleção de conjuntos disjuntos. Ela suporta duas operações principais: Find: descobre a qual conjunto um elemento pertence, retornando o "representante" (raiz) do conjunto. Union: une dois conjuntos em um só. A mágica está em duas otimizações que tornam as operações quase O(1): Path Compression: quando fazemos Find, fazemos todos os elementos no caminho apontarem diretamente para a raiz, achatando a árvore para buscas futuras. Union by Rank: sempre anexamos a árvore menor na maior, mantendo a altura logarítmica. Com ambas otimizações, a complexidade amortizada é O(α(n)), onde α é a função inversa de Ackermann - cresce tão devagar que para todos os fins práticos é constante (α(n) <= 4 para n até 10^80).

Path compression achata a árvore durante Find, e union by rank mantém árvores balanceadas. Juntos, tornam operações praticamente O(1).

Passo a Passo

  1. Inicialize cada elemento como seu próprio conjunto (parent[i] = i)
  2. Para Find, siga os ponteiros até a raiz, comprimindo o caminho
  3. Para Union, encontre as raízes e conecte a menor na maior
  4. Para verificar conexão, compare as raízes

Análise de Complexidade

⏱️Tempo
O(alpha(n))

alpha(n) é a função inversa de Ackermann, praticamente constante.

Ver prova

Com path compression e union by rank, qualquer sequência de m operações em n elementos leva O(m * alpha(n)) tempo.

💾Espaco
O(n)

Arrays parent e rank com n elementos.

🎯Melhor Caso
O(1)

Se o elemento já aponta para a raiz.

⚠️Pior Caso
O(alpha(n))

Mesmo no pior caso, alpha(n) <= 4 para valores práticos.

Comparação com Outros Algoritmos

AlgoritmoTempoEspacoMelhor Para
Union-Find(atual)O(alpha(n)) amortizadoO(n)Conectividade dinâmica, Kruskal MST
DFS/BFSO(V + E)O(V)Travessia única, caminho mais curto

Dicas e Erros Comuns

  • Esquecer path compression (Find fica O(n) no pior caso)
  • Esquecer union by rank (árvores desequilibradas)
  • Unir elementos em vez de raízes
  • Não inicializar parent corretamente

Perguntas de Entrevista

Pratique respondendo a perguntas comuns de entrevistas tecnicas. Clique em uma pergunta para iniciar uma sessao de pratica com IA.

Implementacao

python
1class UnionFind:Definição da Classe
2 def __init__(self, n):Definição da Classe
3 self.parent = list(range(n))Inicializar Parent
4 self.rank = [0] * nInicializar Rank
5
6 def find(self, x):Operação Find
7 if self.parent[x] != x:Operação Find
8 self.parent[x] = self.find(self.parent[x])Path Compression
9 return self.parent[x]Operação Find
10
11 def union(self, x, y):Operação Union
12 px, py = self.find(x), self.find(y)Operação Union
13 if px == py:Verificar Conexão
14 return False # Ja conectadosVerificar Conexão
15
16 # Union by rankUnion by Rank
17 if self.rank[px] < self.rank[py]:Union by Rank
18 px, py = py, pxUnion by Rank
19 self.parent[py] = pxUnion by Rank
20 if self.rank[px] == self.rank[py]:Union by Rank
21 self.rank[px] += 1Union by Rank
22 return True
23
24 def connected(self, x, y):Verificar Conexão
25 return self.find(x) == self.find(y)Verificar Conexão
26
27
28# Exemplo: detectar ciclo
29def has_cycle(n, edges):
30 uf = UnionFind(n)
31 for u, v in edges:
32 if not uf.union(u, v):
33 return True # Ciclo encontrado
34 return False
35