coldwa.st
All guidesProgrammingWebDataToolsDatabasesHaskellConceptsCabal & buildsToolchainCompilerPerformanceEditor & HLS

Programacao · conceitos · algoritmos

O que e a notacao Big O?

Por ColdwastAtualizado a 14 jul. 20268 min de leitura#algorithms#complexity#concepts
Grande plano de codigo de programacao colorido num ecra
Big O nao se refere a rapidez com que uma maquina executa o seu codigo - refere-se a forma como o tempo de execucao cresce a medida que a entrada aumenta.

A notacao Big O e uma forma de descrever como o tempo de execucao de um algoritmo (ou o uso de memoria) cresce a medida que a sua entrada aumenta. Responde a uma pergunta: quando a quantidade de dados duplica, ou cresce mil vezes, o seu codigo continua rapido, abranda um pouco, ou fica completamente travado? Ignora deliberadamente os segundos exatos e a velocidade da maquina, e foca-se na forma do crescimento - porque e isso que decide se o codigo que funciona com 100 itens ainda funciona com 100 milhoes.

Porque nao medir simplesmente o tempo?

Porque os segundos dependem da maquina, da linguagem, do compilador e do que mais estiver a correr. Execute o mesmo codigo num portatil e num servidor e obtera numeros diferentes. O Big O deita fora tudo isso e mede algo mais duravel: como o trabalho escala com o tamanho da entrada, geralmente chamado de n. Dois algoritmos podem ambos demorar "alguns milissegundos" com entradas pequenas, mas um mantem-se rapido em escala enquanto o outro se torna inutilizavel. O Big O e a forma de os distinguir antes de chegarmos a esse limite.

As complexidades comuns, da melhor a pior

Estes sao os ritmos de crescimento que vai encontrar com mais frequencia, do que escala melhor ao mais perigoso:

NotacaoNomeIdeia geral
O(1)ConstanteO mesmo trabalho independentemente do tamanho da entrada - por exemplo, ler array[5].
O(log n)LogaritmicaReduz o problema a metade em cada passo - por exemplo, a pesquisa binaria.
O(n)LinearO trabalho cresce em conjunto com a entrada - por exemplo, percorrer uma lista uma vez.
O(n log n)LinearitmicaO melhor que se consegue para ordenacao geral - por exemplo, o mergesort.
O(n²)QuadraticaUm ciclo dentro de um ciclo - aceitavel para 100 itens, doloroso para um milhao.
O(2ⁿ)ExponencialDuplica a cada elemento adicionado - apenas utilizavel para entradas minusculas.
O(n!)FatorialTodas as ordenacoes possiveis da entrada - pratico apenas para n muito pequeno.

Porque as constantes e os termos pequenos sao descartados

O Big O preocupa-se com o crescimento, nao com contagens exatas, por isso simplifica. Se um algoritmo faz 2n + 3 passos, escreve-se O(n): o 2 e o 3 nao alteram a forma da curva a medida que n cresce. Da mesma forma, n² + n torna-se O(n²), porque o termo quadratico domina assim que n e grande. E por isso que o Big O se refere ao termo dominante - a parte que decide o comportamento em escala - e nao a uma leitura precisa de cronometro.

Um cronometro mecanico antigo com mostrador preto
O Big O ignora o cronometro. Mede como o trabalho cresce com a entrada, nao quantos segundos demora uma execucao.

Um exemplo concreto

Suponha que quer verificar se uma lista contem um duplicado. Uma abordagem compara cada item com todos os outros - dois ciclos aninhados, aproximadamente n × n comparacoes, ou seja O(n²). Outra abordagem adiciona cada item a um hash set e verifica a pertenca a medida que avanca - uma unica passagem, ou seja O(n). Com 1.000 itens, a versao quadratica faz cerca de um milhao de comparacoes; com 100.000 itens faz dez mil milhoes, enquanto a versao linear faz 100.000. A mesma tarefa, destinos radicalmente diferentes em escala. Essa diferenca e exatamente o que o Big O foi construido para expor.

Pior caso, caso medio e melhor caso

A rigor, o Big O descreve um limite superior - geralmente o pior caso, o maximo de trabalho que o algoritmo poderia fazer. Vai tambem encontrar dois familiares: Big Omega (Ω) para o melhor caso, um limite inferior, e Big Theta (Θ) quando o melhor e o pior crescem ao mesmo ritmo, dando um limite estreito. No dia a dia, as pessoas dizem "Big O" de forma solta para significar o crescimento no pior caso, porque e em torno disso que se planeia: quer saber quao mau pode ficar, nao a sorte que ocasionalmente pode ter.

Complexidade de espaco, tambem

A mesma notacao descreve a memoria, nao apenas o tempo. Um algoritmo que copia toda a entrada para uma nova estrutura usa O(n) de espaco extra; um que reorganiza a entrada no lugar usa O(1) de espaco extra. Com grandes volumes de dados, a memoria pode ser o verdadeiro limite, por isso vale a pena perguntar tanto "como cresce o tempo?" como "como cresce a memoria?".

Como raciocinar sobre o seu proprio codigo

  • Conte os ciclos sobre a entrada. Uma unica passagem e geralmente O(n); um ciclo dentro de um ciclo sobre os mesmos dados e geralmente O(n²).
  • Reduzir a metade e um logaritmo. Se cada passo descarta metade dos dados restantes (como a pesquisa binaria), isso e O(log n).
  • As consultas num hash map/set sao ~O(1). Substituir uma varredura aninhada por uma consulta hash e a forma classica de transformar O(n²) em O(n).
  • Descarte as constantes. Tres passagens unicas separadas continuam a ser O(n), nao O(3n) - o que importa e a forma.

FAQ

Um Big O mais baixo e sempre mais rapido? Em escala, sim - mas nem sempre para entradas pequenas. As constantes e a sobrecarga que o Big O ignora podem fazer um metodo O(n²) superar um O(n log n) num punhado de itens. O Big O diz-lhe quem ganha a medida que os dados crescem, o que e geralmente o que importa.

Qual e a melhor complexidade possivel? O(1), tempo constante - o trabalho nao cresce de todo com a entrada. A seguir vem O(log n). Para problemas que tem de olhar para cada item pelo menos uma vez, O(n) e o minimo.

Porque e que O(n log n) e especial para ordenacao? E o limite inferior comprovado para a ordenacao geral baseada em comparacoes, por isso o mergesort, o heapsort e boas implementacoes de quicksort visam-no todas. Nao e possivel, em geral, ordenar dados arbitrarios mais depressa apenas por comparacoes.

Preciso de Big O para programar no dia a dia? Nao precisa da matematica formal, mas a intuicao e inestimavel: reconhecer quando um ciclo aninhado vai explodir com uma entrada grande, ou quando uma consulta hash o salva, evita classes inteiras de bugs de desempenho.

Guia independente, mantido pela comunidade. coldwa.st e um site de recursos de programacao; este explicativo cobre a notacao Big O a nivel introdutorio. As complexidades e os exemplos sao resultados padrao das ciencias da computacao.