Como escrever códigos mais rápidos e escaláveis

Ian Guimarães
5 min readMay 17, 2021

--

Me deparei com essa pergunta um dia e pensei: Por que não escrever um artigo a respeito disso?

Dentro da matemática, existe uma notação chamada Big-O. Essa função descreve o comportamento limitante de uma função, quando o argumento tende a um valor particular ou ao infinito. Ficou confuso? Deixa que eu te explico!

Essa notação, quando trazida para a programação, é uma forma de classificar o quão escalável é o seu código.

Gráfico do Big-O Notation

Como você pode observar, existe diferentes cores dentro do gráfico. Nós podemos interpretar essas cores como diferentes tipos de códigos escritos e o seu tempo de execução de acordo com a quantidade de inputs (dados colocados para rodar no seu código)

Logo, se você escreve um código e provê 100 milhões de dados para ele processar, e a complexidade do seu código é a vermelha (O(n²)), então seu código é muuuito lento e nenhum um pouco escalável.

O que as cores representam e como classificar um algoritmo no gráfico

Agora que vimos o gráfico e entender como a base da Big-O Notation funciona, vamos entender como funciona cada uma dessas notações/corzinhas e o que elas representam.

O(1) ou Cor Verde

O(1) ou complexidade de tempo constante. Essa é a mais simples de todas. Basicamente, não importa quantos dados você prover, 1 milhão ou 1, o algoritmo sempre levará o mesmo tempo para executar. Como você pode observar no gráfico, é a complexidade mais rápida e mais escalável de todos os outros.

E quais tipos de algoritmos são representados pelo O(1)?

Operações simples. Soma, multiplicação, divisão, subtração de valores, criar variáveis, retornar valores de uma map…

Exemplos de códigos O(1)

O(log N) ou Cor Amarela

A partir daqui, tudo vai depender da quantidade de inputs inseridos. Vamos entender!

Digamos que nós tenhamos uma lista de 0 a 10 já ordenada e queiramos procurar pelo número 8 dentro dessa lista. Oras, é simples, vamos rodar um for e checar se o número atual é o número que estamos procurando, vai funcionar!

Sim, vai funcionar, mas, a complexidade desse código será O(n), pois ele precisará passar por todos os inputs até chegar no valor que ele quer. Parece bobeira quando falamos de 0 a 10, mas, e se trocássemos para 0 a 2 milhões e quiséssemos o número 1.525.733? Passar por cada um dos números agora parece uma má ideia, não?

Para evitarmos esse gasto de desempenho a toa, podemos utilizar um algoritmo que se chama binary search e tem como o objetivo obter o número que desejamos em complexidade O(log N).

O binary search funciona de forma muito simples. Suponhamos que temos 0–10 em uma lista e estamos querendo o número 7. Ao invés de buscar o número 7 por cada elemento da lista, ele irá buscar pelo valor do meio da lista, que é o 5. Como sabemos que a lista está ordenada, então nós podemos descartar todos os valores anteriores ao cinco, dividindo a lista em 5 pra cima. Depois, pegamos o valor do meio e repartimos a lista ao meio novamente utilizando as mesmas regras anteriores. E, quando não houver mais nada para dividir ou não houver mais intervalos, então significa que encontramos o número 7.

Exemplo de binary search

O(n) ou Cor Azul

A velocidade do algoritmo é baseada na quantidade de dados inserido pelo usuário, simples. Quanto menos, mais rápido ele irá rodar, quanto mais dados, pior o desempenho.

Ou seja, o O(n) é uma curva linear, que aumenta o tempo de execução conforme a quantidade de dados.

E quais tipos de algoritmos são representados pelo O(n)?

Passar pelos elementos de uma lista, comparar duas strings…

Esse algoritmo é O(n), porque esse for executará até acabar todos os elementos da lista. Como temos 6 elementos, o código irá executar rapidamente. Entretanto, 1 milhão de elementos, faria com que demorasse muito mais tempo.

O(n²) ou Cor Vermelha

As coisas começam a ficar perigosas aqui. O n² é o a quantidade dos seus inputs elevada ao quadrado, n * n.

Ou seja, uma vez que você inserir uma array com 8 elementos, por exemplo, ela virará 64. Isso é ruim, muito ruim. Porque, se inserirmos 1 milhão de inputs, então virará 1 BILHÃO de inputs para processar.

E quais tipos de algoritmos são representados pelo O(n²)?

Bubble Sort, Insertion Sort, Selection Sort, passar por uma uma lista 2D… Vejamos um exemplo de código que busca pelo elemento repetido dentro da lista:

Exemplo de código O(n²) que busca pelo número repetido em uma lista

O segundo for irá rodar 8x para cada elemento do primeiro for, que também possuí 8 elementos, fazendo com que esse código passe por 64 elementos ao total.

A recomendação é que você evite códigos assim a qualquer custo, pois podem trazer um grande problema para a sua aplicação no futuro.

E sobre as outras notações?

Sim, existe outras, como a n!, n log n e 2^n. Mas acho que é bacana comentar sobre eles em outra oportunidade em um artigo mais aprofundado. A ideia nesse aqui é só passar uma visão geral sobre como a Big O Notation funciona.

Acho que chegamos ao fim de mais um artigo, espero que eu tenha conseguido te ajudar a entender um pouco mais sobre como funciona as notações e que agora você tenha um norte sobre complexidade de tempo de um código.

Nesse artigo, eu também citei alguns tipos de algoritmos de busca e de ordenamento conhecidos como o Linear Search, Bubble Sort… Mas acabei por não entrar a fundo, que tal em outra oportunidade? O que você acha?

Vou ficando por aqui, a gente se vê em breve. Até!

--

--

Ian Guimarães
Ian Guimarães

Written by Ian Guimarães

Olá 👋, eu sou o Ian e seja bem vindo ao meu blog. Sou desenvolvedor há 4 anos e atuo como backend. Adoro compartilhar conhecimento e ajudar as pessoas!

Responses (1)