Se você já é um usuário ativo de ChatGPT, esta aula introdutória pode soar um tédio. Acesse conteúdos mais avançados e interessantes no painel ao lado.
Ideal para quem está explorando possibilidades com a ferramenta. Lembre-se: você pode obter resultados diferentes daqueles aqui reproduzidos.
Ideal para quem já tem domínio da ferramenta e busca integrações e engenharia de prompts.

Entrevistas de Algoritmos

Carta de Paulo Luan
Dev Front-End e Co-Fundador #jobnagringa
Este conteúdo foi atualizado em  
07/2024

Entrevistas de algoritmos são difíceis. Mas felizmente, existe um método testado e aprovado para melhorar nelas. Com uma combinação de estudar, praticar perguntas e fazer entrevistas simuladas, conseguir o emprego dos sonhos pode se tornar uma realidade, até mesmo numa Big Tech.

Em geral, esses são os passos que você deve seguir para mandar bem na entrevista técnica:

  1. Estudar os fundamentos da Ciência da Computação (Algoritmos, Estrutura de Dados e System Design)
  2. Praticar a resolução de questões de algoritmo.
  3. Saber o que fazer e o que não fazer em entrevistas.
  4. Conhecer quais os sinais e comportamentos que os entrevistadores estão em busca em cada uma das etapas.
  5. Praticar entrevistas simuladas e se comunicar com tranquilidade.
  6. Passar em uma entrevista com sucesso, conseguir a vaga, ser feliz e comprar uma Porsche.

Recapitulando os fundamentos da Ciência da Computação

Se você está fora da faculdade faz um tempo, você vai precisar revisar os fundamentos da Ciência da Computação como algoritmos e estruturas de dados.

Sugestão de Estudo

  1. Faça o Curso de Programação dinâmica do Henrique Bastos (Duração: 1h 25m)
  2. Faça o Curso de algoritmos do ThePrimeagen. (Duração: 9h 20m)

Os cursos acima são a base mínima que você precisa para entender os tópicos de base antes de iniciar as seções abaixo.

Outros recursos interessantes opcionais

  1. Esse repositório pode servir como um recurso para refrescar a memória.
  2. Esse perfil do Medium também é um recurso leve e bacana para recapitular os vários algoritmos e estruturas de dados.
  3. Você também pode encontrar implementações de algoritmos e estruturas de dados simples usando várias linguagens populares em TheAlgorithms.

Domínio através da prática

Você pode praticar exercícios desse tipo participando de maratonas de programação. Lá pelo menos você vai se divertir e praticar os exercícios de forma deliberada. Em casa, você pode particar com os exercícios resolvidos deste repositório do Cracking the Coding Interview. Outra forma são através dos diversos sites de competição de programação como LeetCode, HackerRank e CodeForces.As questões do LeetCode são mais similares às questões que serão perguntadas em entrevistas enquanto as do HackerRank e CodeForces lembram questões de programação competitivas. Caso seja uma pessoal mais visual, esse curso do Coderust explica questões de algoritmo comuns através de visualizações passo-a-passo, o que torna a compreensão das soluções muito mais fácil.

Complexidades de tempo/espaço

Aprenda e entenda as complexidades de tempo e espaço de operações comuns na sua linguagem de programação. Para Python, essa página é bem útil. Se estiver boiando você precisa ver o curso do Henrique Bastos focando na aula de complexidade assintótica. Como boa prática é recomendado após completar uma questão no LeetCode, sempre incluir as complexidades de tempo e espaço do código escrito em forma de comentários acima do corpo da função, assim você se lembrará de analisar o algoritmo assim que terminar sua implementação. Isso é particularmente útil, porque sempre o entrevistador vai querer saber dessa informação.

Internalize as armadilhas

Descubra e familiarize-se com as armadilhas comuns e ressalvas da linguagem. Se apontá-las durante a entrevista e evitar, inteligentemente, de cair nelas, normalmente você impressionará o entrevistador e isso resulta em pontos bônus em seu feedback, independente se o entrevistador estiver familiarizado com a linguagem ou não.

Amplie a exposição

Adquira uma ampla exposição às questões de vários tópicos. Nos próximos módulos você verá diversos tópicos de algoritmo e questões para praticar em cada um deles. Faça em torno de 100-200 questões do LeetCode e você será bom. Pratique.

Algumas linguagens são mais adequadas para entrevistas

Existem algumas linguagens que são mais adequadas do que outras para entrevistas de código e algumas linguagens você definitivamente vai querer evitar. A maioria dos candidatos escolhe Python ou Java. Outras linguagens vistas normalmente incluem JavaScript, Ruby e C++. Evite linguagens de baixo nível como C ou Go, simplesmente porque elas não têm muitas funções e estruturas de dados de biblioteca padrão, e algumas podem exigir gerenciamento manual de memória. Python é uma boa pedida para entrevistas de código e algoritmo, porque é sucinta e tem uma gigantesca biblioteca de funções e estruturas de dados disponíveis. Você pode alcançar muito com o mínimo da sintaxe em Python.

Utilize uma linguagem que você domine

Na maior parte do tempo, é recomendável que você utilize uma linguagem que você é extremamente familiarizado em vez de escolher uma linguagem nova apenas para fazer entrevistas porque a empresa usa muito tal linguagem ou só porque você quer mostrar que segue tendências. Se você está com limitações de tempo, aprender uma nova linguagem apenas para entrevistas não é uma boa ideia. Siga no que você entende e não perca tempo. Tem muita coisa a se estudar, não adicione uma linguagem a essa lista.

Comunique seu Pensamento Durante a Entrevista de Código

Seu entrevistador estará procurando por sinais de que você preenche os requisitos da função e cabe a você exibir esses sinais a ele. Comunique-se a todo instante. É extremamente difícil para o entrevistador saber o que você está pensando apenas olhando para o código que você digita. Inicialmente, pode parecer estranho conversar enquanto você programa, visto que a maioria dos devs não tem o hábito de explicar em voz alta enquanto estão trabalhando, mas você precisa explicar sua linha de raciocínio a todo tempo. Se você comunicar sua abordagem ao entrevistador antes de iniciar o código, você pode validar suas idéias e ambos podem concordar sob uma perspectiva aceitável em relação ao problema e a sua solução.

Ao receber a questão

Muitos candidatos começam a criar código no momento que ouvem a questão. Isso é normalmente um grande erro. Leve um momento e repita a pergunta de volta para o entrevistador e certifique-se de que entendeu exatamente o que estão solicitando. Repetir de volta/frasear novamente a questão reduzir as chances de falha de comunicação.

Busque sempre clareza sobre a questão ao ouvi-la mesmo que julgue estar clara para você. Você pode descobrir algo que acabou escapando e também envia um sinal ao entrevistador de que você é uma pessoa cuidadosa que presta atenção aos detalhes. Só comece a codificar após você e seu entrevistador concordar sobre uma abordagem e ele tiver dado a luz verde a você. Alguns entrevistadores omitem intencionalmente os detalhes importantes para checar se você vai fazer as perguntas certas.

Algumas perguntas comuns que você pode fazer:

  • Qual o tamanho da entrada?
  • Qual o comprimento dos valores?
  • Que tipo de valores existem? Existem números negativos? Pontos flutuantes? Haverão entradas vazias?
  • Existem duplicatas na entrada?
  • Quais são alguns dos casos extremos da entrada?
  • Posso destruir o vetor/grafo/estrutura de dados original?
  • Como a entrada é armazenada? Se for dado um dicionário de palavras, será uma lista de strings ou uma árvore de prefixos?

Após ter esclarecido o suficiente o escopo e a intenção do problema, explique sua abordagem de alto nível ao entrevistador mesmo que seja uma solução completamente estúpida. Se você travar, considere várias abordagens e explique em alto, e bom-tom porque irá/não irá funcionar. Às vezes seu entrevistador pode dar algumas dicas e guiar você no caminho certo. Fique atento, se o entrevistador te perguntar "Podemos fazer melhor?", isso significa que ele está procurando por uma abordagem melhor em relação a que você fez.

Você pode procurar por algum código repetido e tentar otimizá-lo utilizando, potencialmente, cache para o resultado calculado em algum lugar e referenciando-o mais tarde, em vez de ter que computá-lo todo novamente.

O que fazer quando travar?

Travar durante entrevistas de código é extremamente comum. Mas não se preocupe, isso faz parte do processo e é um teste das suas habilidades de solução de problemas. Aqui vão algumas dicas que você pode experimentar quando estiver travado:

Passo Descrição
Fale sobre o que você pensou inicialmente que poderia funcionar e explique porque não funciona Isso pode ajudar a guiá-lo ao caminho certo, evitando as armadilhas
Crie mais casos de teste e anote-os Um padrão ou alguma ideia pode surgir
Pense como você resolveria sem um programa em si Você pode encontrar um padrão e criar um algoritmo genérico
Relembre questões passadas relacionadas ao tópico, quais questões parecidas você encontrou no passado e quais técnicas você utilizou? (aqui a importância de treinar exercícios no Leetcode)
Enumere as estruturas de dados comuns e se podem ser aplicadas à questão Dicionários/mapas são extremamente comuns para tornar os algoritmos mais eficientes
Procure por trabalho repetido e determine se pode empregar cache nesses cálculos

Durante a criação do código

Entender o código dos outros pode ser uma tarefa árdua, e quando está mal formatado, torna-se ainda mais complicado. A chave está em escrever código limpo. Seu objetivo é permitir que o entrevistador compreenda rapidamente o que você escreveu, avaliando se cumpre sua função e resolve o problema proposto. Use nomes de variáveis descritivos, evitando abreviações excessivas, a menos que explicadas previamente. Se estiver escrevendo código em uma lousa, considere abreviar variáveis para economizar tempo, mas assegure-se de explicar o significado das abreviações. Durante a codificação, comunique-se com o entrevistador sobre o que está fazendo e por que está fazendo, em um nível mais alto. Isso não significa narrar cada linha digitada, mas explicar o contexto e a lógica por trás do código em questão.

Após a criação do código

  1. Após ter finalizado a codificação, não anuncie imediatamente ao entrevistador que você terminou. Na maioria das vezes, seu código não está perfeito e contem alguns bugs ou erros de sintaxe. O que você precisa fazer agora é revisar seu código.
  2. Primeiramente, percorra seu código do começo ao fim como se fosse a primeira vez que está olhando, como se tivesse sido escrito por outra pessoa e você está tentando encontrar bugs nele. É exatamente o que seu entrevistador estará fazendo. Vasculhe e corrija quaisquer erros menores que possa encontrar.
  3. Em seguida, crie pequenos casos de teste e aplique-os ao seu código (não ao seu algoritmo!) com uma entrada grande.
  4. O que os entrevistadores geralmente fazem após você ter terminado de escrever o código é justamente o que faz você escrever testes. É um enorme ponto forte se você escrever testes para seu código mesmo antes de solicitarem que você os faça.
  5. Você deve emular um depurador quando estiver percorrendo o código e anotar ou dizer claramente os valores de variáveis importantes conforme avança pelas linhas de código.
  6. Se existirem enormes porções de código duplicadas em sua solução, seria uma boa oportunidade de refatorá-las e demonstrar ao entrevistador que você valoriza a qualidade do código.
  7. Por último, forneça a complexidade de tempo e espaço do seu código e explique o porquê. Você pode até anotar certas porções de código com várias complexidades de tempo e espaço para demonstrar seu entendimento do código e as APIs da linguagem de programação escolhida.
  8. Explique quaisquer compensações da sua abordagem atual e outras alternativas, possivelmente com respeito ao tempo/espaço.

Se o seu entrevistador estiver satisfeito com a solução que você apresentou, geralmente é a hora de encerrar a conversa. No entanto, é comum que ele também faça perguntas adicionais para avaliar mais a fundo suas habilidades. Por exemplo, ele pode questionar como você lidaria com o problema se os dados fossem grandes demais para caber na memória ou se fossem fornecidos de forma contínua ao invés de estar em um arquivo estático. Isso é particularmente relevante em empresas como a Google, que valorizam muito a escalabilidade de suas soluções. Uma resposta típica seria adotar uma abordagem de "dividir para conquistar". Isso envolve distribuir o processamento dos dados e ler apenas partes específicas do conjunto de entrada, armazenando temporariamente os resultados no disco antes de combiná-los posteriormente.

Cronograma de Algoritmos

Aqui está um cronograma sugerido para revisar e praticar perguntas de algoritmo no LeetCode.

Ao praticar, é aconselhado você tratá-la como uma entrevista de código real e verificar cuidadosamente antes de enviar. Considere até mesmo criar manualmente alguns casos de teste e executá-los para verificar a exatidão.

Semana 1 - Sequências

Na semana 1 você encontra uma mistura de perguntas fáceis e médias sobre vetores e strings. Ambas são as perguntas mais comuns encontrados em entrevistas; familiarizar-se com eles ajudará na construção de fundamentos sólidos para lidar melhor com questões mais difíceis:

Exercícios Propostos:

Opcional

Semana 2 - Estruturas de Dados

O foco da semana 2 está em listas encadeadas, strings e questões baseadas em matriz. O objetivo é aprender as rotinas comuns que lidam com listas encadeadas, atravessar matrizes e técnicas de análise de sequência (vetores / strings), como sliding window.

Exercícios Propostos:

Semana 3 - Estruturas de Dados Não-Lineares

O foco da semana 3 são as estruturas de dados não lineares como árvores, grafos e pilhas. Você deve estar familiarizado com os vários algoritmos de travessia de árvore (em ordem, pré-ordem, pós-ordem) e algoritmos de travessia de grafo, como busca em largura e busca em profundidade.

Exercícios Propostos:

Opcional

Semana 4 - Mais Estruturas de Dados

A semana 4 é construída sobre o conhecimento das semanas anteriores, mas as questões apresentam dificuldade crescente. Espere ver esse nível de perguntas durante as entrevistas. Você adquire mais prática em estruturas de dados mais avançadas, como (mas não exclusivamente limitado a) heaps e árvores de prefixos.

Exercícios Propostos:

Opcional

Semana 5 - Programação Dinâmica

A semana 5 foca nas questões de Programação Dinâmica (PD).

Esse tipo de exercício pode parecer distante da realidade cotidiana, mas algumas empresas, como o Google, ainda incluem perguntas de Pensamento Divergente (PD) em suas entrevistas. Se você almeja trabalhar em uma Big Tech, enfrentar essas questões pode se tornar inevitável. Dominar as perguntas de PD pode ser desafiador, mas a prática é a chave para melhorar. É importante se familiarizar com conceitos como memorização e retrocesso. No entanto, é crucial reconhecer que o retorno do investimento (ROI) ao estudar e praticar para essas questões pode ser limitado. Portanto, as perguntas de PD podem ser consideradas menos prioritárias ou até opcionais, devendo ser abordadas apenas por aqueles que estão genuinamente interessados em cobrir todos os aspectos possíveis.

Semana 6 - Encontrando padrões comuns.

A sexta e última semana, temos a coleção dos algoritmos mais importantes - e comuns - em entrevistas algoritmicas no geral. Vale a pena investir um tempo e pesquisar com mais profundidade sobre cada uma delas.

Exercícios adicionais:

  1. Algoritmos mais comuns em entrevistas:
  2. Top k largest elements.
  3. Sliding window.
  4. Combination Sum Backtracking.
  5. Combination Sum Dynamic Programming.
  6. DFS and BFS.
Carta de Paulo Luan
Dev há 14 anos. Estruturou a arquitetura de diversas startups americanas. Mentorou mais de 6k devs.
Esta aula foi planejada e está sendo desenvolvida no momento. Em breve será adicionada aqui.
Conheça o Repositório de Question & Answers #JNG

Preparamos um banco de perguntas e respostas técnicas que potencialmente podem ser abordadas em diversas áreas

Acesse o Q&A Repo