Algoritmos & Estruturas de Dados
Roadmap completo de DSA para entrevistas e fundamentos de engenharia. Cada tópico inclui visualizadores interativos, complexidade e exercícios selecionados do LeetCode com dicas de resolução.
Navegação Rápida
Arrays & Strings
Sequência contígua na memória com acesso O(1) por índice. Strings são sequências de caracteres (imutáveis na maioria das linguagens). A base de quase todos os problemas de entrevista.
Acesso: O(1) · Busca: O(n) · Inserção/Remoção: O(n) (append: O(1) amortizado)
Two Sum
Encontra dois números que somam ao target usando hash map. O(n) tempo, O(n) espaço.
1function twoSum(nums, target) {2 const map = new Map();34 for (let i = 0; i < nums.length; i++) {5 // Calcula o complemento necessário6 const complement = target - nums[i];78 // Verifica se o complemento já foi visto9 if (map.has(complement)) {10 return [map.get(complement), i];11 }1213 // Armazena o valor atual e seu índice14 map.set(nums[i], i);15 }1617 return [];18}Array: [2, 7, 11, 15, 1, 8, 3] — Target: 9
Exercícios LeetCode
5 problemasDica: Use hash map para lookup O(1) do complemento
Dica: Mantenha o mínimo visto até agora e calcule o lucro em cada passo
Dica: Dois passes: prefix product da esquerda e suffix product da direita
Dica: Two pointers das extremidades, movendo o ponteiro menor
Dica: Para cada posição, água = min(maxLeft, maxRight) - height. Use two pointers ou prefix max
Hash Tables
Estrutura que mapeia chaves a valores usando função hash. Inserção, busca e remoção em O(1) no caso médio. Pior caso O(n) com colisões.
Inserção: O(1) amortizado · Busca: O(1)* · Remoção: O(1)* (*caso médio)
Hash Table
Inserção com função hash e resolução de colisões por chaining.
1class HashTable {2 constructor(size = 7) {3 this.buckets = new Array(size).fill(null).map(() => []);4 this.size = size;5 }67 hash(key) {8 let h = 0;9 for (const ch of key) h = (h + ch.charCodeAt(0)) % this.size;10 return h;11 }1213 set(key, value) {14 const idx = this.hash(key);15 const bucket = this.buckets[idx];16 // Verifica se a chave já existe (atualiza)17 const existing = bucket.find(([k]) => k === key);18 if (existing) existing[1] = value;19 else bucket.push([key, value]);20 }2122 get(key) {23 const idx = this.hash(key);24 const pair = this.buckets[idx].find(([k]) => k === key);25 return pair ? pair[1] : undefined;26 }27}Hash table com 7 buckets vazia
Exercícios LeetCode
5 problemasDica: Conte a frequência de cada caractere com hash map
Dica: Use a string ordenada como chave do hash map
Dica: Coloque tudo num Set. Para cada início de sequência (n-1 não existe), conte o comprimento
Dica: Prefix sum + hash map: conta quantos prefix sums anteriores = prefixSum - k
Dica: Hash map + doubly linked list. Map aponta para nodes da lista
Two Pointers
Técnica que usa dois ponteiros percorrendo o array (geralmente das extremidades para o centro, ou ambos do início). Reduz O(n²) para O(n).
Tempo: O(n) · Espaço: O(1)
Two Pointers — Two Sum II
Dois ponteiros convergem em array ordenado para encontrar par com soma alvo. O(n).
1function twoSumSorted(numbers, target) {2 let left = 0;3 let right = numbers.length - 1;45 while (left < right) {6 const sum = numbers[left] + numbers[right];78 if (sum === target) {9 return [left, right];10 } else if (sum < target) {11 // Soma muito pequena, avança esquerda12 left++;13 } else {14 // Soma muito grande, recua direita15 right--;16 }17 }1819 return [-1, -1];20}Array ordenado. Target = 13. left=0, right=6
Exercícios LeetCode
4 problemasDica: left e right convergem, ignorando não-alfanuméricos
Dica: Two pointers clássico: soma < target → left++, soma > target → right--
Dica: Ordene, fixe um elemento, use two pointers no restante. Pule duplicatas
Dica: Mova sempre o ponteiro com menor altura (não pode melhorar mantendo ele)
Sliding Window
Janela que desliza sobre uma sequência, mantendo um estado agregado. Evita recalcular do zero a cada posição. Ideal para subarrays/substrings contíguos.
Tempo: O(n) · Espaço: O(1) ou O(k)
Sliding Window — Max Sum Subarray
Janela deslizante de tamanho fixo para encontrar soma máxima. O(n).
1function maxSumSubarray(arr, k) {2 let windowSum = 0;34 // Soma da primeira janela5 for (let i = 0; i < k; i++) {6 windowSum += arr[i];7 }8 let maxSum = windowSum;910 // Desliza a janela11 for (let i = k; i < arr.length; i++) {12 // Remove elemento que saiu, adiciona novo13 windowSum = windowSum - arr[i - k] + arr[i];1415 // Atualiza o máximo16 maxSum = Math.max(maxSum, windowSum);17 }1819 return maxSum;20}Array: [2, 1, 5, 1, 3, 2, 8, 1, 3] — Janela de tamanho k=3
Exercícios LeetCode
5 problemasDica: Sliding window degenerado: mantenha mínimo à esquerda, calcule lucro
Dica: Janela variável + Set/Map. Quando encontrar duplicata, encolha a janela pela esquerda
Dica: Janela fixa do tamanho de s1. Compare frequências de caracteres
Dica: Janela variável: expanda pela direita até conter tudo, encolha pela esquerda para minimizar
Dica: Monotonic deque: mantém índices em ordem decrescente de valor
Binary Search
Busca em espaço ordenado descartando metade a cada passo. Não se limita a arrays — funciona em qualquer espaço de busca monotônico.
Tempo: O(log n) · Espaço: O(1)
Binary Search
Busca em array ordenado dividindo o espaço pela metade. Complexidade O(log n).
1function binarySearch(arr, target) {2 let low = 0;3 let high = arr.length - 1;45 // Continua enquanto houver espaço de busca6 while (low <= high) {7 // Calcula o índice do meio8 const mid = Math.floor((low + high) / 2);910 if (arr[mid] === target) {11 // Elemento encontrado!12 return mid;13 } else if (arr[mid] < target) {14 // Descarta metade esquerda (valores menores)15 low = mid + 1;16 } else {17 // Descarta metade direita (valores maiores)18 high = mid - 1;19 }20 }2122 // Elemento não encontrado23 return -1;24}Buscando 9 no array ordenado
Exercícios LeetCode
5 problemasDica: Implementação clássica. Cuidado com mid = left + (right - left) / 2
Dica: Trate a matriz como array 1D: index → row = i/cols, col = i%cols
Dica: Binary search na resposta: busque o menor k tal que termina em h horas
Dica: Uma metade sempre está ordenada. Determine qual e se o target está nela
Dica: Binary search no menor array. Particione ambos para que left_total = right_total
Prefix Sum
Pré-computa somas acumuladas para responder consultas de range em O(1). Base para muitos problemas de subarray e programação competitiva.
Construção: O(n) · Consulta: O(1)
Prefix Sum
Pré-computa somas acumuladas para consultas de range em O(1).
1function buildPrefixSum(arr) {2 const prefix = [0];34 // Constrói o array de prefix sum5 for (let i = 0; i < arr.length; i++) {6 prefix.push(prefix[i] + arr[i]);7 }89 return prefix;10}1112// Consulta de range em O(1)13function rangeSum(prefix, left, right) {14 return prefix[right + 1] - prefix[left];15}Array original: [3, 1, 4, 1, 5, 9, 2, 6]
Exercícios LeetCode
4 problemasDica: Implementação direta de prefix sum
Dica: prefix[j] - prefix[i] = k ↔ prefix[i] = prefix[j] - k. Use hash map
Dica: Pré-compute prefix sum no construtor, responda queries em O(1)
Dica: Prefix product pela esquerda × suffix product pela direita
Linked Lists
Coleção de nós onde cada nó aponta para o próximo. Inserção/remoção em O(1) dado o ponteiro, mas acesso por índice é O(n). Trade-off oposto ao array.
Acesso: O(n) · Busca: O(n) · Inserção/Remoção: O(1)* (*dado o ponteiro)
Reverse Linked List
Inverte uma linked list iterativamente com 3 ponteiros. O(n).
1function reverseList(head) {2 let prev = null;3 let curr = head;45 while (curr !== null) {6 // Salva o próximo nó7 const next = curr.next;89 // Inverte o ponteiro10 curr.next = prev;1112 // Avança prev e curr13 prev = curr;14 curr = next;15 }1617 // prev é o novo head18 return prev;19}Lista original: 1 → 2 → 3 → 4 → 5
Exercícios LeetCode
5 problemasDica: Três ponteiros: prev, current, next. Inverta os links iterativamente
Dica: Use dummy head. Compare e avance o ponteiro menor
Dica: Floyd's tortoise and hare: slow (1 passo) e fast (2 passos). Se encontram → ciclo
Dica: 3 passos: encontre o meio, inverta segunda metade, intercale as duas metades
Dica: Min-heap com k elementos (um de cada lista). Extraia o mínimo e insira o próximo
Stacks & Queues
Stack: LIFO (Last In, First Out). Queue: FIFO (First In, First Out). Fundamentais para parsing, BFS, DFS e problemas de ordem.
Push/Pop/Enqueue/Dequeue: O(1)
Valid Parentheses
Valida parênteses usando stack. Push aberturas, pop e compare fechamentos.
1function isValid(s) {2 const stack = [];3 const pairs = { ')': '(', ']': '[', '}': '{' };45 for (const ch of s) {6 if ('([{'.includes(ch)) {7 // Abertura: push na stack8 stack.push(ch);9 } else {10 // Fechamento: verifica match11 if (stack.length === 0 || stack[stack.length - 1] !== pairs[ch]) {12 return false;13 }14 // Match: pop da stack15 stack.pop();16 }17 }1819 // Válido se stack vazia20 return stack.length === 0;21}Validar: "({[]})"
Exercícios LeetCode
5 problemasDica: Stack: push abertura, pop e compare ao encontrar fechamento
Dica: Dois stacks: um normal e um que rastreia o mínimo atual
Dica: Stack de operandos. Ao encontrar operador: pop dois, calcule, push resultado
Dica: Monotonic stack decrescente. Ao encontrar temp maior: pop e calcule distância
Dica: Monotonic stack crescente. Para cada barra: calcule largura usando stack
Trees (Binary Tree & BST)
Estrutura hierárquica com nós e arestas. Binary Search Tree (BST) mantém: esquerda < raiz < direita, permitindo busca em O(log n) quando balanceada.
BST balanceada — Busca/Inserção/Remoção: O(log n)
BST In-Order Traversal
Percorre BST em ordem (L → Root → R), produzindo elementos ordenados.
1function inOrderTraversal(root) {2 const result = [];34 function inOrder(node) {5 if (node === null) return;67 // Visita subárvore esquerda8 inOrder(node.left);910 // Processa o nó atual11 result.push(node.val);1213 // Visita subárvore direita14 inOrder(node.right);15 }1617 inOrder(root);18 return result; // Retorna valores em ordem crescente19}BST com 7 nós. In-order traversal: L → Root → R
Exercícios LeetCode
5 problemasDica: Recursão: troque left e right de cada nó, recursivamente
Dica: return 1 + max(depth(left), depth(right)). Base: null → 0
Dica: Passe min/max bounds recursivamente. Ou: in-order traversal deve ser crescente
Dica: BFS com fila. Processe level.length nós por nível
Dica: Pre-order com marcador "null". Deserialize com fila/índice recursivo
Heaps / Priority Queue
Árvore binária completa onde cada pai ≥ filhos (max-heap) ou ≤ filhos (min-heap). Representada como array. Essencial para top-k, mediana e scheduling.
Insert: O(log n) · Extract Min/Max: O(log n) · Peek: O(1) · Build: O(n)
Min-Heap Insert
Insere elementos no min-heap com bubble up. O(log n) por inserção.
1class MinHeap {2 constructor() { this.heap = []; }34 insert(val) {5 // Adiciona no final6 this.heap.push(val);78 // Bubble up: troca com pai enquanto menor9 let idx = this.heap.length - 1;10 while (idx > 0) {11 const parent = Math.floor((idx - 1) / 2);12 if (this.heap[parent] <= this.heap[idx]) break;13 // Troca com o pai14 [this.heap[parent], this.heap[idx]] = [this.heap[idx], this.heap[parent]];15 idx = parent;16 }17 }18}Inserindo valores: [5, 3, 8, 1, 4, 7, 2] em min-heap
Exercícios LeetCode
5 problemasDica: Min-heap de tamanho k. O topo é sempre o k-ésimo maior
Dica: Max-heap. Extraia os dois maiores, insira a diferença se > 0
Dica: Max-heap de tamanho k por distância. Ou quickselect para O(n) médio
Dica: Max-heap de frequências + cooldown queue. Simule ciclos
Dica: Dois heaps: max-heap (metade menor) + min-heap (metade maior). Balance os tamanhos
Tries (Prefix Tree)
Árvore onde cada aresta representa um caractere. Busca por prefixo em O(m) onde m é o comprimento da palavra. Usado em autocomplete e spell checkers.
Insert: O(m) · Search: O(m) · Prefix Search: O(m)
Trie Insert
Insere palavras na Trie (prefix tree). Busca por prefixo em O(m).
1class TrieNode {2 constructor() {3 this.children = {};4 this.isEnd = false;5 }6}78class Trie {9 constructor() { this.root = new TrieNode(); }1011 insert(word) {12 let node = this.root;1314 for (const ch of word) {15 // Cria nó se não existe16 if (!(ch in node.children)) {17 node.children[ch] = new TrieNode();18 }19 // Avança para o filho20 node = node.children[ch];21 }2223 // Marca fim de palavra24 node.isEnd = true;25 }26}Inserir palavras: [cat, car, dog]
Exercícios LeetCode
3 problemasDica: Nó com children[26] + isEnd. Insert/search/startsWith iterativos
Dica: Trie + DFS. "." wildcard: tente todos os filhos recursivamente
Dica: Construa trie das palavras. DFS na grid usando o trie como guia. Prune ramos vazios
Graphs — BFS & DFS
Grafos modelam relações entre entidades. BFS explora nível a nível (menor caminho em grafos não-ponderados). DFS explora em profundidade (ciclos, componentes conexos).
BFS/DFS: O(V + E) · Espaço: O(V)
BFS — Busca em Largura
Explora todos os vizinhos antes de avançar para o próximo nível. Usa fila FIFO.
1function bfs(graph, start) {2 const visited = new Set();3 // Fila FIFO para controlar a ordem de visita4 const queue = [start];56 while (queue.length > 0) {7 // Remove o primeiro da fila8 const node = queue.shift();910 if (visited.has(node)) continue;11 // Marca o nó como visitado12 visited.add(node);13 console.log("Visitando:", node);1415 // Adiciona todos os vizinhos não visitados à fila16 for (const neighbor of graph[node]) {17 if (!visited.has(neighbor)) {18 queue.push(neighbor);19 }20 }21 }22}2324// Exemplo de grafo como lista de adjacência25const graph = {26 A: ["B", "C"],27 B: ["A", "D", "E"],28 C: ["A", "F", "G"],29 D: ["B", "H"],30 E: ["B"],31 F: ["C", "I"],32 G: ["C"],33 H: ["D"],34 I: ["F"],35};3637bfs(graph, "A");Início: A adicionado à fila
Exercícios LeetCode
5 problemasDica: DFS/BFS em cada "1" não visitado. Marque como visitado. Conte componentes
Dica: DFS + hash map old→new. Crie clone ao visitar, conecte vizinhos recursivamente
Dica: Detecte ciclo em grafo direcionado. Topological sort com DFS ou Kahn's (BFS)
Dica: BFS/DFS reverso: comece dos oceanos e suba. Interseção = resposta
Dica: BFS onde cada palavra é um nó. Vizinhos: palavras que diferem em 1 caractere
Algoritmos de Ordenação
Organizar elementos em ordem. Lower bound de comparação: Ω(n log n). Entender trade-offs entre estabilidade, espaço e caso médio vs pior caso.
Comparação: Ω(n log n) · Não-comparativo: O(n+k) ou O(d·n)
Merge Sort
Divide recursivamente e combina metades ordenadas. O(n log n) garantido.
1function mergeSort(arr) {2 // Caso base: array de 1 elemento já está ordenado3 if (arr.length <= 1) return arr;45 // Divide o array ao meio6 const mid = Math.floor(arr.length / 2);7 const left = mergeSort(arr.slice(0, mid));8 const right = mergeSort(arr.slice(mid));910 // Combina as duas metades ordenadas11 return merge(left, right);12}1314function merge(left, right) {15 const result = [];16 let i = 0, j = 0;1718 // Compara elementos das duas metades e insere o menor19 while (i < left.length && j < right.length) {20 if (left[i] <= right[j]) {21 result.push(left[i]);22 i++;23 } else {24 result.push(right[j]);25 j++;26 }27 }2829 // Copia os elementos restantes de cada metade30 return result.concat(left.slice(i), right.slice(j));31}Array inicial
Exercícios LeetCode
4 problemasDica: Dutch National Flag: 3 ponteiros (low, mid, high). Particione em 0s, 1s, 2s
Dica: Counting + bucket sort por frequência. Ou heap de tamanho k
Dica: Quickselect (partição do quicksort): O(n) médio. Ou min-heap de tamanho k
Dica: Ordene por start. Itere e merge se overlap (current.start <= last.end)
Recursão & Backtracking
Construir soluções incrementalmente e abandonar caminhos inválidos (pruning). Gera permutações, combinações e resolve constraint satisfaction problems.
Tempo: O(2ⁿ) ou O(n!) com pruning · Espaço: O(n) stack
Subsets — Backtracking
Gera todos os subsets de [1,2,3] usando árvore de decisão.
1function subsets(nums) {2 const result = [];34 function backtrack(start, current) {5 // Adiciona o subset atual ao resultado6 result.push([...current]);78 // Tenta incluir cada elemento restante9 for (let i = start; i < nums.length; i++) {10 current.push(nums[i]); // escolha11 backtrack(i + 1, current); // explora12 current.pop(); // desfaz (backtrack)13 }14 }1516 backtrack(0, []);17 return result;18}Gerar todos os subsets de [1, 2, 3]
Exercícios LeetCode
5 problemasDica: Para cada elemento: incluir ou não incluir. Backtrack gerando todas combinações
Dica: Para cada posição, tente cada número não usado. Backtrack removendo do resultado
Dica: Backtrack com reutilização. Ordene e pule se candidato > remaining target
Dica: Uma rainha por linha. Verifique coluna e diagonais. Use sets ou bitmask para O(1) check
Dica: DFS na grid. Marque visitado, tente 4 direções, desmarque ao voltar (backtrack)
Programação Dinâmica
Resolve problemas com subproblemas sobrepostos e subestrutura ótima. Memoization (top-down) ou tabulação (bottom-up). Reduz complexidade exponencial para polinomial.
Tempo: O(estados × transição) · Espaço: O(estados)
Climbing Stairs (DP)
dp[i] = dp[i-1] + dp[i-2]. É Fibonacci! O(n) tempo, O(n) espaço.
1function climbStairs(n) {2 // Cria tabela DP3 const dp = new Array(n + 1);45 // Casos base6 dp[0] = 1; // 1 forma de ficar parado7 dp[1] = 1; // 1 forma de subir 1 degrau89 // Preenche bottom-up10 for (let i = 2; i <= n; i++) {11 dp[i] = dp[i - 1] + dp[i - 2];12 }1314 return dp[n];15}Climbing Stairs: quantas formas de subir 6 degraus? (1 ou 2 passos)
Exercícios LeetCode
5 problemasDica: dp[i] = dp[i-1] + dp[i-2]. É literalmente Fibonacci!
Dica: dp[i] = max(dp[i-1], dp[i-2] + nums[i]). Roubar ou pular
Dica: dp[amount] = min(dp[amount - coin] + 1) para cada moeda. Unbounded knapsack
Dica: O(n²): dp[i] = max(dp[j]+1) para j<i com arr[j]<arr[i]. O(n logn): patience sort
Dica: 2D DP: dp[i][j] = custo para transformar s1[0..i] em s2[0..j]. 3 operações
Greedy Algorithms
Faz a escolha localmente ótima a cada passo, esperando encontrar o ótimo global. Funciona quando a "greedy choice property" é satisfeita.
Geralmente O(n log n) com sort + O(n) scan
Interval Scheduling (Greedy)
Seleciona máximo de atividades não-conflitantes. Ordena por fim.
1function intervalScheduling(intervals) {2 // Ordena por tempo de fim3 intervals.sort((a, b) => a[1] - b[1]);45 const selected = [];6 let lastEnd = -Infinity;78 for (const [start, end] of intervals) {9 // Se não conflita com o último selecionado10 if (start >= lastEnd) {11 // Seleciona esta atividade12 selected.push([start, end]);13 lastEnd = end;14 }15 }1617 return selected;18}7 atividades ordenadas por fim. Greedy: escolha a que termina primeiro.
Exercícios LeetCode
5 problemasDica: Kadane's: maxEndingHere = max(num, maxEndingHere + num). Greedy local → global
Dica: Mantenha o alcance máximo (farthest). Se i > farthest, impossível
Dica: BFS implícito: a cada "nível" (range), calcule o próximo farthest. Conte níveis
Dica: Se total_gas >= total_cost, solução existe. Reset start quando tank < 0
Dica: Ordene. Use hash map de frequências. Para cada menor carta, tente formar grupo
Intervals
Problemas envolvendo intervalos [start, end]. Pattern: ordene por start ou end, depois itere verificando overlaps/merges.
Sort: O(n log n) + Scan: O(n) = O(n log n)
Merge Intervals
Ordena por start e merge intervalos sobrepostos. O(n log n).
1function mergeIntervals(intervals) {2 // Ordena por start3 intervals.sort((a, b) => a[0] - b[0]);45 const merged = [intervals[0]];67 for (let i = 1; i < intervals.length; i++) {8 const last = merged[merged.length - 1];910 // Verifica overlap11 if (intervals[i][0] <= last[1]) {12 // Merge: estende o end13 last[1] = Math.max(last[1], intervals[i][1]);14 } else {15 // Sem overlap: novo intervalo16 merged.push(intervals[i]);17 }18 }1920 return merged;21}5 intervalos ordenados por start.
Exercícios LeetCode
4 problemasDica: Ordene por start. Se current.start <= last.end: merge (max dos ends)
Dica: Adicione antes, merge overlaps no meio, adicione depois. Três fases
Dica: Greedy: ordene por end. Conte conflitos (keep o que termina antes)
Dica: Ordene por end. Se balloon.start > arrow, nova flecha. Senão, já estoura
Bit Manipulation
Operações diretamente nos bits: AND, OR, XOR, shifts. Extremamente eficiente — uma instrução CPU. Usado em masks, flags e otimizações.
Operações bitwise: O(1)
Single Number (XOR)
XOR de todos: duplicados se cancelam, sobra o único. O(n) tempo, O(1) espaço.
1function singleNumber(nums) {2 let result = 0;34 // XOR de todos os elementos5 for (const num of nums) {6 result ^= num;7 }89 // Duplicados se cancelam (a^a=0)10 // Resta apenas o único11 return result;12}Array: [4, 1, 2, 1, 2]. Encontrar o número único usando XOR.
Exercícios LeetCode
5 problemasDica: XOR todos: a^a=0, 0^b=b. Todos duplicados se cancelam, sobra o único
Dica: n & (n-1) remove o lowest set bit. Conte quantas vezes até n=0
Dica: dp[i] = dp[i >> 1] + (i & 1). Ou dp[i] = dp[i & (i-1)] + 1
Dica: Extraia cada bit (n & 1), shift no resultado, shift no n. 32 iterações
Dica: XOR de 0..n com todos os elementos. Duplicados cancelam, sobra o faltante
Grafos Avançados
Topological Sort para DAGs, Union-Find para componentes conexos, Dijkstra para menores caminhos ponderados. Problemas que vão além de BFS/DFS simples.
Topo Sort: O(V+E) · Union-Find: O(α(n)) por operação · Dijkstra: O((V+E) log V)
Topological Sort (Kahn's)
Ordena nós de um DAG respeitando dependências. BFS com in-degree.
1function topologicalSort(numNodes, edges) {2 // Constrói grafo e calcula in-degrees3 const adj = Array.from({length: numNodes}, () => []);4 const inDegree = new Array(numNodes).fill(0);56 for (const [u, v] of edges) {7 adj[u].push(v);8 inDegree[v]++;9 }1011 // Enfileira nós com in-degree 012 const queue = [];13 for (let i = 0; i < numNodes; i++) {14 if (inDegree[i] === 0) queue.push(i);15 }1617 const order = [];1819 while (queue.length > 0) {20 const node = queue.shift();21 order.push(node);2223 // Reduz in-degree dos vizinhos24 for (const neighbor of adj[node]) {25 inDegree[neighbor]--;26 // Se in-degree chega a 0, enfileira27 if (inDegree[neighbor] === 0) {28 queue.push(neighbor);29 }30 }31 }3233 return order;34}Kahn's Topological Sort. In-degrees: {"0":0,"1":1,"2":1,"3":2,"4":1}
Exercícios LeetCode
5 problemasDica: Topological sort (Kahn's BFS): comece pelos nós com in-degree 0
Dica: Union-Find: adicione arestas uma a uma. Se find(u) == find(v), é redundante
Dica: Union-Find ou DFS na adjacency matrix. Conte quantos roots/componentes distintos existem
Dica: Dijkstra com min-heap. Retorne o max dos tempos mínimos
Dica: Topological sort reverso: nós terminais são safe. Remova arestas de trás pra frente (ou DFS com 3 cores)