Hogyan lehet bármilyen algoritmus-interjút megközelíteni pánik nélkül

Legyünk őszinték, az algoritmusproblémák továbbra is nagyrészt az álláskeresés részét képezik. Bár folyamatosan bővül azoknak a vállalatoknak a listája, amelyek nem kényszerítik a kódolási karikák átugrására, az átlag fejlesztő valamikor az álláskeresés során élő algoritmus kihívással fog találkozni. Különösen, ha Nagy Négynél vagy egy már beindult vállalkozásnál akarsz dolgozni. Tehát a karikákon át ugrunk.

Nem kell arról beszélnem, mennyire megterhelőek lehetnek a technikai interjúk. Biztos vagyok benne, hogy a legtöbben ismerjük azt a frusztráltságot, amikor kimerültünk egy interjúból, amelyet éppen lebombáztunk, és biciklizni minden olyan módon, amit meg tudtunk volna fordítani. Nem szórakoztató érzés.

Ezért írom ezt. Azok számára, akik valóban algoritmus-kihívásba kerülnek, az a különbség lehet, hogy hogyan áll hozzá. Ön olyan ember, aki fejest ugrik, és kitalálja útközben? Vagy van olyan folyamatod, amelyet követsz, hogy kezelhető darabokra bontsd a problémát? Míg az előbbi módszer egyesek számára beválhat, én az utóbbit gyakorolom.

Számomra létfontosságú, hogy a probléma lebontásához használjunk néhány lépést. Bár nem garantál megoldást vagy állásajánlatot, lehetővé teszi a stresszválasz kezelését. A pánik elviselhető szinten tartása segít az összpontosításban. Végül is a technikai interjúknak a problémamegoldás képességének bemutatásáról kell szólniuk, nem pedig arról, hogy képesek-e több embert némán elbírálni anélkül, hogy elájulnának.

Ebben a cikkben szeretném bemutatni azt a folyamatot, amelyet több technikai képernyőn és tucatnyi álinterjún keresztül csiszoltam. Erősen befolyásolja a Launch School PEDAC rendszere. Minden egyes alkalommal használom, és jól szolgált.

"Szeress bele a folyamatba, és az eredmények eljönnek." - Eric Thomas

A folyamatom bemutatásának legjobb módja az, ha azt működés közben bemutatom. Tehát dolgozzunk együtt egy problémát. És hogy ez a lehető leghitelesebb legyen, kiválasztok egy problémát, amelyet még soha nem oldottam meg. Bár szót kell fogadnod érte.

Leetcode szerint a String to Integ algoritmus népszerű interjúkérdés. Ez a közepes rangsorolási problémák közül a legalacsonyabb teljesítési arányt is jelenti. Ez jó kihívás lehet.

Ezt a problémát is választottam, mivel kissé praktikus. Ez egy tényleges algoritmus, amelyet a legtöbb programozási nyelvben alkalmaztak. Számos más interjúkkal ellentétben (rád nézve Coin Change) a mérnökök valóban ezt az algoritmust használták a való életben.

Ezzel mondjuk, merüljünk be. Nyugodtan kövesse végig, amit csak akar. JavaScriptet fogok használni. Kipróbálhatja a megközelítésemet, vagy használhatja a sajátját. Nézze meg, meg tudja-e oldani, mielőtt ezt a bejegyzés végén megtenném. Előfordulhat, hogy egy lépéssel közelebb kerül saját nyelvünk létrehozásához.

1. lépés: Átfogalmazza a problémát saját szavaival

Számomra ez a legfontosabb lépés. Ez az esélyem arra, hogy kérdéseket tegyek fel kérdezőimnek a követelmények tisztázása és az összes fontos információ elemzése érdekében. Továbbá a probléma szavakba átírása lehetőséget ad arra, hogy mentális modellt alkossak és megemésztessem a problémát.

Ehhez a problémához feltennék egy kérdést, hogy engedélyezem-e a típus casting használatát. Bár a leírás nem határozza meg, én csak a JavaScript natív típusú castingját használom egy-egy karakter átalakításához. Ez az a fajta korlátozás, amelyet elvárhatok egy tényleges interjú során.

A leírás elolvasása után ezek a legfontosabb részletek, amelyekkel előálltam.

// 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).

Csak ezekből a követelményekből kezdem elképzelni, hogyan fogom létrehozni ezt az algoritmust. Valószínűleg szükség lesz némi ciklusra és elég sok feltételes logikára.

Néhány ember valószínűleg e lépés után kezdene el kódolni. Számomra még mindig túl korai megfogalmazni konkrét terveket - de a sebességem megfordul.

2. lépés: Bemeneti és kimeneti típusok

Sokan értelmetlen lépésnek fogják tekinteni ezt, de mindig ügyelek arra, hogy megkapjam az algoritmus be- és kimeneteit. Vagy kódmegjegyzésként, vagy a tábla sarkában.

Két funkciót tölt be. Először megszilárdítja, hogy milyen funkciói lesznek a paramétereim, és hogy fog kinézni az aláírás. A Leetcode már létrehozta számomra a funkció aláírását, de ez egy konkrét interjúban nem így lesz.

Másodszor emlékeztetem azokat a típusokat, amelyekkel dolgozni fogok. Nem hallatlan, hogy egy jelölt az összes tesztesetet megbukta, mert elfelejtett egy karakterláncot és nem egy tömböt visszaadni. Lehet, hogy tapasztalatból beszélek, vagy nem ...

Problémánkra a bemenet és a kimenet szépen meg van határozva a címben.

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

3. lépés: Példák és éles esetek

Most, hogy biztos vagyok az inputokban és outputokban, szeretnék előállni néhány tesztesettel. Ezeknek a példáknak ki kell terjedniük az összes olyan éles esetre, amelyre gondolni tudok. Csak azt tudom elképzelni, hányszor készített egy működő jelölt egy működő megoldást, csak hogy az interjúkészítő előálljon egy olyan éles esettel, amelyet elmulasztottak - ami miatt a megoldásuk szétesett.

Lehetséges, hogy az interjúztatója ad néhányat, de én még többet találnék ki - főleg, ha ezek nem teljesek. Például a Leetcode adott nekem néhány tisztességes tesztesetet.

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

Ezek a példák azonban hiányolnak néhány lehetőséget. Mi van, ha a szám a-val kezdődik +? Vagy mi van, ha több jel kerül egy szám elé, például -+-50?

Készítsünk néhány jobbat.

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!

Valóban sok időt töltök a hangulat tervezésével. Ha egy kérdező 45 percet ad a befejezéshez, 15–30 percet fogok tölteni gondolkodással és szellemi emésztéssel.

- Adj hat órát, hogy vágjam le a fát, és az első négyet a fejsze megélezésével töltem. - Abraham Lincoln

Valójában a kódolás a legkevésbé fontos lépés számomra. Az összes nehéz emelés már megtörtént. Most csak a mentális modellemet kell kódba értelmeznem.

Ezenkívül az, hogy hogyan kódolom ezt a megoldást egy interjúban, nem ugyanaz, mint ahogy a valós életben kódolom. A fene egy igazi interjúmegoldás másképp nézne ki, mint az a válasz, amelyet erre a cikkre adtam. Számos tényező befolyásolja az interjúk kódolásának módját, például az idő és a kérdező válaszkészsége.

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!