Skip to main content

3 maneiras de melhorar sua solução de entrevista de codificação - a musa

Mark Zuckerberg & Yuval Noah Harari in Conversation (Abril 2025)

Mark Zuckerberg & Yuval Noah Harari in Conversation (Abril 2025)
Anonim

Então você está aí. Aliviado. Exausta. Você finalmente chegou a uma abordagem para resolver a difícil questão de codificação que seu entrevistador lhe faz. Talvez você tenha escrito no quadro branco, linha por linha. E você fez bom tempo! Você está a apenas 20 minutos da reunião. Seu entrevistador deve ficar impressionado.

Certo?

“Isso funcionará, mas alguma ideia de como fazer isso de maneira mais eficiente?”

Seu coração afunda. Você pensou que você tinha acabado com a parte do projeto de algoritmo complicado! Você tenta pensar em mais maneiras de resolver o problema, mas tudo o que você pode pensar é a abordagem que você já desenvolveu.

Isso acontece com quase todo mundo. E não é porque eles são estúpidos. É porque a maioria das pessoas não tem um método para melhorar a eficiência de seus algoritmos.

Mas a verdade é que há muito. Da próxima vez que você ficar perplexo, tente aplicar essas três abordagens comuns.

1. Use um Mapa de Hash

Está certo. Mapas de hash / matrizes / dicionários associativos (eles usam vários nomes, dependendo da linguagem de programação que você está usando) têm uma habilidade mágica de reduzir o tempo de execução de algoritmos.

Por exemplo, suponha que a pergunta seja encontrar o número mais repetido em uma matriz de números.

Seu primeiro pensamento pode ser pular em alguns loops. Para cada um dos nossos números, descubra sua contagem e veja se é o maior deles. Como podemos obter a contagem para cada número? Faça um loop pelo array, contando quantas vezes isso ocorre! Então estamos falando de dois loops aninhados. No pseudocódigo:

def get_mode (nums): max_count = 0 mode = null para potential_mode em nums: count = 0 para number em our_array: count + = 1 se contar> = max_count: mode = potential_mode max_count = count return mode

No momento, estamos percorrendo toda a matriz uma vez para cada item da matriz, mas podemos fazer melhor. Em grande notação O, esse é o tempo (n 2 ) no total.

Se armazenarmos nossas contagens em um mapa hash (mapeando os números para suas contagens), poderemos resolver o problema em apenas uma caminhada pelo array (O (n) time!):

def get_mode (nums): max_count = 0 modo = null counts = new HashMap, iniciando cada valor em 0 para potential_mode em nums: counts + = 1 if counts> max_count: mode = em potencial_modo max_count = contagens em modo de retorno

Muito mais rapido!

2. Use Manipulação Bit

Isso realmente vai te diferenciar do pacote. Isso não se aplica a todos os problemas, mas se você mantiver isso no bolso de trás e eliminá-lo no momento certo, você se parecerá com um astro do rock.

Veja um exemplo: suponha que tenhamos uma matriz de números, em que cada número aparece duas vezes, exceto por um número que ocorre apenas uma vez. Estamos escrevendo uma função para encontrar o número solitário e não repetido.

Seu primeiro instinto pode ser usar um mapa hash, já que falamos sobre isso. Isso é um bom instinto para ter! E vai funcionar para este. Podemos criar um mapa de "contagens" muito semelhante e usá-lo para ver qual número termina com uma contagem de 1.

Mas há um jeito ainda melhor. Se você estiver familiarizado com a manipulação de bits, você pode estar familiarizado com o XOR. Uma coisa que é especial sobre o XOR é que se você XOR um número com ele mesmo, os bits “cancelam” para 0. Para este problema, se nós todos os XOR juntos no array, ficaremos com o número que não cancelar:

def find_unrepeated (nums): não repetido = 0 para num nums: não repetido = sem repetição XOR num retornar sem repetição

3. Vá de baixo para cima

Escreva uma função que emita o “n” número de Fibonacci, dado um número n. Este é um clássico e se presta muito bem à recursão:

def fib (n): se n é 0 ou 1: retorna 1 retorna fib (n-1) + fib (n-2)

Mas a resposta recursiva simples não é a única! Pense cuidadosamente sobre o que esta função faz. Suponha que n seja 5. Para obter a resposta, ela chama recursivamente de fib (4) e fib (3). Agora, o que isso chama de fib (4)? Chama fib (3) e fib (2). Mas acabamos de dizer que já recebemos uma ligação para o fib (3)! Esta função recursiva atraente faz muito trabalho repetido. O custo total do tempo é O (2 n ). Isso é ruim - muito pior que O (n 2 ).

Em vez de ir de n recursivamente até 1, vamos "bottom-up", de 1 a n. Isso nos permite pular a recursão:

def fib (n): anterior = 0 previous_previous = 1 para i no intervalo de 1 a n: atual = anterior + anterior_ anterior anterior_ anterior = anterior anterior = atual

O código é mais longo, mas é muito mais eficiente! Down to O (n) tempo. Como um bônus adicional com o desenrolar de algoritmos recursivos, economizamos espaço. Todas as chamadas recursivas se acumulam na pilha de chamadas, que fica na memória e conta para o nosso custo de espaço. Nossa função recursiva tinha um custo de espaço O (n), mas esse iterativo ocupa o espaço O (1).

Na próxima vez que seu entrevistador solicitar que você melhore a eficiência de sua solução, tente analisar essas estratégias e ver se elas ajudam. Com prática suficiente, você provavelmente se encontrará na solução otimizada, ignorando a solução mais ingênua. E isso é ótimo. Isso não significa apenas que você está se tornando um melhor entrevistador - significa que você está se tornando um engenheiro melhor.