Cómo abordar cualquier entrevista de algoritmo sin entrar en pánico

Seamos honestos, los problemas de algoritmos siguen siendo una parte importante de la búsqueda de empleo. Si bien hay una lista en constante expansión de empresas que no lo hacen pasar por los aros de la codificación, el desarrollador promedio se encontrará con un desafío de algoritmo en vivo en algún momento de su búsqueda de trabajo. Especialmente si quieres trabajar para una Big Four o una startup establecida. Así que saltamos a través de los aros.

No necesito hablar sobre lo estresante que pueden ser las entrevistas técnicas. Estoy seguro de que la mayoría de nosotros conoce la frustración de salir de una entrevista que acabamos de bombardear y recorrer todas las formas en que podríamos haber cambiado. No es un sentimiento divertido.

Por eso escribo esto. Para aquellos de ustedes que terminan en un desafío de algoritmos, la forma en que lo aborden puede marcar la diferencia. ¿Eres el tipo de persona que se lanza de cabeza y lo descubre en el camino? ¿O tiene un proceso que sigue para dividir el problema en partes manejables? Si bien el primer método puede funcionar para algunos, yo ejercito el segundo.

Para mí, tener un conjunto de pasos para analizar un problema es crucial. Si bien no me garantiza una solución u oferta de trabajo, me permite administrar mi respuesta al estrés. Mantener mi pánico a un nivel tolerable me ayuda a concentrarme. Después de todo, las entrevistas técnicas deben tratar de demostrar su capacidad para resolver problemas, no su capacidad para manejar a varias personas que lo juzgan en silencio sin desmayarse.

En este artículo, quiero mostrarles el proceso que he perfeccionado a través de varias pantallas técnicas y decenas de entrevistas simuladas. Está fuertemente influenciado por el sistema PEDAC de Launch School. Lo uso todo el tiempo y me ha servido bien.

"Enamórate del proceso y los resultados vendrán". - Eric Thomas

La mejor forma de mostrar mi proceso es demostrarlo en acción. Así que trabajemos juntos en un problema. Y para que esto sea lo más auténtico posible, elegiré un problema que nunca antes había resuelto. Aunque tendrás que creer en mi palabra.

Según Leetcode, el algoritmo String to Integer es una pregunta de entrevista popular. También tiene la tasa de finalización más baja de todos los problemas de clasificación media. Este debería ser un buen desafío.

También elegí este problema porque es algo práctico. Este es un algoritmo real que se ha implementado en la mayoría de los lenguajes de programación. A diferencia de muchos otros desafíos de entrevistas (mirándote Coin Change), los ingenieros han utilizado este algoritmo en la vida real.

Dicho esto, vamos a sumergirnos. Siéntete libre de seguirlo en el idioma que quieras. Usaré JavaScript. Puede probar mi enfoque o usar el suyo. Vea si puede resolverlo antes que yo al final de esta publicación. Podría terminar un paso más cerca de crear nuestro propio idioma.

Paso 1: reformule el problema con sus propias palabras

Para mí, este es el paso más importante. Esta es mi oportunidad de hacerle preguntas a mi entrevistador para aclarar los requisitos y analizar toda la información crucial. Además, reescribir el problema en mis palabras me da la oportunidad de formar un modelo mental y digerir el problema.

Para este problema, una pregunta que me gustaría hacer es si puedo usar la conversión de tipos. Si bien la descripción no lo especifica, solo usaré la conversión de tipo nativo de JavaScript para convertir un carácter a la vez. Ese es el tipo de restricción que esperaría encontrar en una entrevista real.

Después de leer la descripción, estos son los detalles clave que se me ocurrieron.

// Given a string, return its appropriate number value.
// Ignore all white-space at the beginning of the string.
// Number may begin with a negative or positive.
// All characters that come after the number should be ignored.
// String is invalid if a character that is not a white-space or sign comes before the number.
// If string does not contain any integer values, it is invalid.
// The return value for any invalid string is 0.
// Resulting integer cannot be larger than (2^31) — 1 or smaller than -(2^31).

Solo a partir de estos requisitos, ya estoy empezando a imaginar cómo crearé este algoritmo. Probablemente requerirá un poco de bucle y bastante lógica condicional.

Algunas personas probablemente comenzarían a codificar después de este paso. Para mí, todavía es un poco pronto para formular planes concretos, pero mis engranajes están girando.

Paso 2: tipos de entrada y salida

Mucha gente verá esto como un paso sin sentido, pero siempre me aseguro de obtener las entradas y salidas del algoritmo. Ya sea como un comentario de código o en la esquina de la pizarra.

Tiene dos funciones. Primero, solidifica cuáles serán los parámetros de mi función y cómo se verá la firma. Leetcode ya creó la firma de la función para mí, pero este no será el caso en una entrevista real.

En segundo lugar, guardo un recordatorio de los tipos con los que trabajaré. No es extraño que un candidato falle en todos los casos de prueba porque se olvidó de devolver una cadena y no una matriz. Puedo o no estar hablando por experiencia ...

Para nuestro problema, las entradas y salidas están bien definidas en el título.

Input: stringOutput: 32-bit signed integerSignature: myAtoi(str)

Paso 3: ejemplos y casos de borde

Ahora que estoy seguro de las entradas y salidas, quiero proponer algunos casos de prueba. Estos ejemplos deben cubrir todos los casos extremos que se me ocurran. Solo puedo imaginar la cantidad de veces que un candidato ha creado una solución de trabajo, solo para que el entrevistador presente un caso límite que se perdió, lo que hizo que su solución se derrumbara.

Es posible que su entrevistador proporcione algunos, pero se me ocurrirán aún más, especialmente si no son exhaustivos. Por ejemplo, Leetcode me ha proporcionado algunos casos de prueba decentes.

In: “4193 with words”Out: 4193
In: “words and 987”Out: 0
In: “-91283472332”Out: -2147483648

Sin embargo, en estos ejemplos faltan algunas posibilidades. ¿Qué pasa si el número comienza con a +? ¿O qué pasa si hay varios signos antes de un número, como -+-50?

Hagamos algunos mejores.

Input: “+50.890”Output: 50
Input: “ -+100”Output: 0
Input: “ !another invalid -10”Output: 0

Step 4: Data Structure(s)

Most, if not all, algorithm code challenges involve using a structure to keep track of your data. It’s important to consider which data structure(s) you will use as it will impact your implementation.

I know from the problem description that I will be dealing with strings and integers. But will I use another data structure to help convert from one to the other?

One issue I can already foresee is keeping track of the places of each digit (tens, hundreds, thousands, etc). Since I will not know the length of my integer beforehand, I will use an array to keep track of the integer characters. The array will serve as the interim placeholder for each character before they are converted into the final integer.

While there is most likely a more space efficient solution, I can optimize my solution later. Right now, I just want to go with what makes the most sense for me. It’s better to get a working naive solution than to shoot for the moon and not finish anything.

Step 5: Pseudocode

My penultimate step is to spend some time laying out my algorithm in pseudocode. Interviewers want to see how you think and approach problems. Pseudocode is perfect for that.

An added benefit is that the interviewer will know how to assist you ahead of time. There have been times where I’ve gotten stuck on a problem only to have my interviewer provide subtle hints to keep me going. If you jump into coding without a plan, you could end up confusing both yourself and your interviewer. Do each of you a favor and create an action plan.

This is what I came up with.

// Start with index = 0
// While character at current index is white-space // increment index
// Check if next character is invalid // return 0
// Check if next character is positive or negative sign // If negative sign, mark number as negative // increment index
// Loop through characters starting at current index // If current character is integer // Unshift into front of array // Increment index // Else, break out of loop
// Loop through string integer array // Cast string character into integer // Multiply integer by (10^index) and add to return value
// If string contained negative sign, multiply result value by -1// If result value is less than min, reassign to min// If result value is greater than max, reassign to max
// return value

It may seem like I came up with this out of nowhere, but there was a lot of deliberation and trial-and-error behind the scenes. This is the most time-consuming step because this is where the algorithm is created.

Read over the requirements, inputs/outputs, and edge cases. Ask questions, clarify concepts, and isolate areas of uncertainty to focus on. Find the simplest solution you can think of and work from there.

Will you need a depth-first search? Sliding window? Divide and conquer? Something else?

If this is the step you struggle with the most, don’t worry. It will get easier with practice. And practice you should. A thorough algorithm design in pseudocode will make the next step fast and easy.

Step 6: Code!

Finally!” You’re probably thinking. “That took forever!

De hecho, dedico mucho tiempo a planificar el estado de ánimo. Si un entrevistador me da 45 minutos para terminar, dedicaré entre 15 y 30 minutos a pensar y digerir mentalmente.

"Dame seis horas para talar un árbol y pasaré las primeras cuatro afilando el hacha". - Abraham Lincoln

De hecho, la codificación es el paso menos importante para mí. Todo el trabajo pesado ya está hecho. Ahora solo necesito interpretar mi modelo mental en código.

Además, la forma en que codifique esta solución en un entorno de entrevista no será la misma que la codifique en la vida real. Diablos, una solución de entrevista real se vería diferente a la respuesta que se me ocurrió para este artículo. Varios factores afectan la forma en que codifico en una entrevista, como el tiempo y la capacidad de respuesta del entrevistador.

Without access to Google or sufficient time to refactor, I just want to write something that works. And there’s no guarantee I would even achieve that.

But that’s not the point of this post. Yes, it’s possible I wouldn’t have solved this question in an interview. But up until this point, I have de-structured the challenge into its key components. I know I can solve it and I have put myself in the best position to do so. A good interviewer will see that.

In a technical screen or onsite, it’s not about the code. It’s how you come up with it.

If you are interested in comparing solutions, here’s the one I came up with:

This solution is not the most efficient. According to Leetcode, it only beats 25% of the other submissions.

However, it would pass most technical interviews. An interviewer might ask me to optimize it for space or time, but those are things that can be included on further iterations if time permits. You don’t need to come up with them on the first try.

The point of using a process is to have a systemic approach to break down any challenge. It works whether you use in your job on a daily basis or in a technical interview. By using it in an interview, you can keep your panic at bay by focusing on the challenge and not your emotions.

If you don’t have a process, start making one. You can use PEDAC or develop your own. Just make sure it helps you create solutions in which you’re confident.

For example, you may have noticed the use of constants, helper functions, and regex in my solution. Those are all tricks I’ve picked up that help me isolate complexity in an interview. The more my code reads like English, the less confused I get when writing it, and the faster I work. It may be a bit verbose, but I like it. Do what works for you.

If there’s already a procedure you use, practice and perfect it. Don’t wait until your onsite interview to start fine-tuning. Experiment in mock interviews. Pramp and Interviewing.io are perfect tools for that.

Remember, if all else fails, trust the process.

If this article has resonated with you, please leave some claps ? !

As always, happy coding!