English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

nu

visitante
1 / ?
voltar às lições

Taxas de Crescimento, Não Custos Absolutos

Big O: Medindo a Velocidade de Crescimento dos Custos

A notação Big O mede a taxa de crescimento do custo de um algoritmo — não o custo absoluto.

A pergunta que Big O responde: quando o tamanho da entrada N dobra, o trabalho dobra? Quadruplica? Fica constante?

O 'O' significa 'ordem de magnitude.' A expressão dentro dos parênteses descreve a forma da curva de crescimento.

Tabela de Crescimento Big O: operações em N=10, 100 & 1.000 para O(1), O(N) & O(N²)

Classes de complexidade principais:

- O(1) — constante: o custo não cresce. Exemplo: procurar um valor pelo índice em um array. Quer o array tenha 10 itens ou 10 milhões, uma busca continua uma busca.

- O(N) — linear: o custo cresce com a entrada. Exemplo: ler cada item em uma lista uma vez. Duplique a lista, duplique as leituras.

- O(N²) — quadrática: o custo cresce como o quadrado da entrada. Exemplo: comparar cada item com todos os outros itens. Duplique N, quadruplique o trabalho.

Tabela de comparação de crescimento:

NO(1)O(N)O(N²)
10110100
100110010.000
1.00011.0001.000.000

Em N=10 a diferença parece pequena. Em N=1.000 a lacuna fica enorme.

Compare O(N) com O(N²)

Use a tabela de comparação de crescimento acima.

Em N=1.000: O(N) requer 1.000 operações. O(N²) requer 1.000.000 de operações.

Em N=1.000, quantas vezes mais operações O(N²) requer em comparação com O(N)? Mostre seus cálculos.

Como a Estrutura do Código Revela Complexidade

Como Identificar Big O a partir do Código

Big O está escondido na forma do seu código. Quatro padrões cobrem a maioria dos casos:

Loop único sobre N itens: O(N)

# O(N): uma passagem pela lista
for item in list_of_n_items:
    process(item)

Loops aninhados, cada um sobre N itens: O(N²)

# O(N²): cada item emparelhado com todos os outros itens
for item_a in list_of_n_items:
    for item_b in list_of_n_items:
        compare(item_a, item_b)

Busca com tempo constante: O(1)

Acesso por índice de array, busca em tabela hash — uma etapa independentemente do tamanho.

Dividir e conquistar (corte o problema pela metade a cada etapa): O(log N)

Busca binária: cada verificação reduz pela metade os itens restantes.

---

O(N²) escondido: uma lista dentro de um loop

# Parece O(N) mas na verdade é O(N²)
visited = []
for item in list_of_n_items:
    if item not in visited:   # scans all of visited: O(N)
        visited.append(item)  # o loop todo: O(N²)

A linha if item not in visited examina cada elemento de visited a cada iteração. Uma varredura de lista custa O(N). Um loop que executa N vezes, cada um fazendo trabalho O(N): O(N) × O(N) = O(N²).

Este padrão aparece em mais de 1.000 projetos de código aberto. A correção leva um caractere: substitua visited = [] por visited = set(). Testes de pertencimento de conjunto custam O(1), não O(N). Uma mudança. Os mesmos resultados. 1.000× mais rápido em N=1.000.

Classifique e Corrija Este Código

Leia este código:

result = []
for name in student_names:
    if name not in result:
        result.append(name)
Qual é a complexidade Big O deste código? Explique por que a linha `if name not in result` a torna cara. Depois reescreva o código para torná-lo O(N).

A Teoria Encontra a Prática

Big O na Prática

Big O não é apenas teoria. Ele separa programas que terminam em segundos de programas que levam 17 minutos — na exata mesma tarefa.

Exemplo real: detecção de ciclo de dependência em um sistema de construção.

Quando você instala software, seu computador resolve um gráfico de dependências: o pacote A precisa de B, B precisa de C, & assim por diante. Um sistema de construção verifica este gráfico para ciclos.

Um algoritmo de detecção de ciclos O(N²) funciona bem em N=100 pacotes. Em N=50.000 pacotes (um projeto real): leva 17 minutos. A correção O(N): 10 segundos.

Este defeito exato existe em GHC (compilador Haskell), pip (gerenciador de pacotes Python), Maven (sistema de construção Java), Cargo (gerenciador de pacotes Rust), & mais de 1.000 outros projetos.

Não porque seus autores foram descuidados. visited = [] foi escrito quando N era pequeno. O código calcificou. N cresceu. Ninguém notou até que a construção levasse meia hora.

Big O é o vocabulário que permite nomear o que aconteceu — & corrigi-lo.

---

Quer explorar mais profundamente? Nosso curso unhamming inclui um capítulo completo sobre Big O, MOAD-0001 (um defeito real O(N²) encontrado em mais de 1.000 projetos de código aberto), & por que nomear um padrão permite encontrá-lo em todos os lugares. Veja O Capítulo Perdido: Complexidade Algorítmica.

Preveja os Tempos de Construção

Um sistema de construção usa detecção de ciclos O(N²).

Tempos de construção medidos:

- N=100 pacotes: 0,01 segundos

- N=1.000 pacotes: 1 segundo

Para O(N²): o tempo se dimensiona como (N_novo / N_antigo)².

Para O(N): o tempo se dimensiona como (N_novo / N_antigo).

Usando essas fórmulas & dados medidos: (A) em N=10.000, quanto tempo leva a versão O(N²)? (B) após uma correção O(N), usando N=1.000 como sua linha de base, quanto tempo leva a versão O(N) em N=10.000? Mostre seus cálculos para ambas.