from Guide to the Job Hunt on Jan 1, 2023
How to succeed at coding interviews.
Most candidates make the mistake of "studying" for coding interviews. Heck, even those that practice coding puzzles are missing the point. Having interviewed 100+ candidates, I can confidently say that the name of the game is communication, not coding.
Interviews are nerve-wracking, and coding interviews at technology companies in particular are notoriously difficult. You've probably heard of the routine by now: Study your algorithms and data structures, practice coding puzzles for several months, then pray to the hiring committee.
However, here's the catch: interviews are very different from the exams that studying prepares you for. They're also very different from the coding exercises that coding puzzles online train you for. Neither common tip helps with the most critical part of an interview — communication, not coding.
To understand how to tackle interviews, you'll need to understand the structure and types of interviews first. There are three categories of interviews:
- Coding Puzzles: These make up the bulk of interviews and technical screens. Since coding puzzles are one of the most commonly discussed, we will focus this post on this category. You can find many of these online. The basic goal is to test your ability to code.
- System Design: This interview asks you to design a "system" from the ground up. A "system" here is very broad: It could be an array of sensors, servers, client-side applications, and other intermediary infrastructure needed to support an application's needs. The basic goal is to test your technical, architectural experience.
- Behavioral: These questions ask you about how you work with others, how you handle challenges, and an array of other "culture"-like questions. The basic goal is to assess how well you would work with the team.
The structure of these interviews is fairly straightforward. In fact, most of your interviewers will open with a paragraph like the following:
I'm writing this introductory paragraph here, so that you can prepare in advance. Here are takeaways from the blurb above:
- Prepare your introduction in advance. This can make interviews less nerve-wracking, given you know exactly how the first 10 minutes will play out. Right now, write a 4-5 sentence introduction of yourself. Say it aloud at least once. It doesn't need to be perfect. Just have talking points you can comfortably recite, without thinking much.
- Prepare questions for your interviewer in advance. Questions at the end are not optional, despite what your interviewer says. Ask questions that are tailored to your interviewer, using their introduction. Ask questions related to your concerns, such as "Does your team prioritize speed or quality? Do you get regular face time with your manager?". Right now, write up 2-3 questions for a company you're interested in. For example, Tesla is known for crazy work hours. You may ask if the team gets weekends to themselves. See What to ask interviewers in a job hunt. for details.
This structure will pervade across all of your interviews, so your preparation above can be reused for many many interviews to come. Since coding interviews are the most common, we will focus this post on coding interviews.
Let's start with the most common interview type: coding interviews. The coding interview puzzles are often unrealistic, extraordinary questions. In response, conventional wisdom says to practice so many coding puzzles that these esoteric questions become second nature. In theory, this is a viable strategy — it's possible to become so fluent in coding puzzles that every interview becomes a breeze. However, there are two, widely recognized problems with this approach:
- This brute force approach is time consuming. Naturally, if you know all questions and memorize all solutions in advance, then yes, you're trivially prepared to solve every possible problem. However, this process can take months, if not more. There are certainly success stories where this paid off, but there are many more untold stories that don't pay off. This section covers why.
- Wasting time on a skill that doesn't generalize beyond interviews. More importantly, spending months and months practicing and memorizing esoteric puzzles is neither (a) pleasant1 or (b) related to the bulk of engineering challenges. The most common complaint about interviews is that it doesn't relate to the job at all. This is true — and why memorizing coding puzzles should not be the skill to develop.
Both of these problems are rooted in one underlying cause: The interview at its core is testing your communication, not your coding puzzle knowledge.
Knowing this, coding on your own for hours on end, in an isolated room, is clearly suboptimal for a communication-focused interview. Instead, you should focus on honing your technical communication; this affords two benefits, allowing you to (1) hone a skill — communication — that does carry over to your job and (2) focus learning only the most common question types, so that vocalizing the types of solutions you're considering is enough for the interviewer to guide you with.
Note that practicing isn't bad, as the knowledge you can gain is useful. However, the habits you build are harmful. Practicing incorrectly leads to the following, easy-to-learn and hard-to-break, habits:
- Think and code in silence. With online coding puzzles, you generally practice on your own, in silence. Once you get a question, you're free to think in silence, lost in your thoughts. You're then free to code in silence, possibly again lost in your thoughts. However, this is not true of interviews, where you need to think and talk, then code and talk.
- Jump straight into code. When practicing alone, you can jump straight into the code, without thinking much. This is reminiscent of homework assignments: Get something down on paper, so you can run the assignment's tests. However, in interviews, jumping straight into code with the wrong algorithm wastes time.
- Test without thinking. Generally speaking, when a test case fails, we'll make a rough assessment, try a fix in code, then rerun the tests. However, making a fix, running tests, making another fix, running tests etc. repeatedly, looks like blind guessing — even if each error is a new bug. Minimize silent debugging, and always explain what you're doing.
To avoid the above bad habits, simply modify how you practice coding puzzles. In essence, the core idea is to think aloud, instead of thinking to yourself silently. Follow these tips:
- Think and code aloud. Vocalizing your thoughts has a key advantage: Interviewers can correct you. In short, interviewers want you to succeed — it makes for a more interesting interview, and it's their role. If you don't say anything, interviewers can't help. In short, practice (1) thinking aloud, then (2) coding and simultaneously explaining. You don't need someone to talk to, just practice consolidating your thoughts into words.
- Design algorithms before coding. Always discuss and design before writing code. Interviewers will rarely introduce a new idea; their role is to tell you which of your existing ideas are worth exploring more, so you should practice throwing out ideas. In short, design the algorithm, and look at the written version of your solutions first, to check your algorithm conceptually. Do this before writing a single line of code. If you get the opportunity to practice with friends, interview each other. Have one friend look at the solution first, then guide the others.
- Run tests "manually". When running your code on new tests, walk through the code line by line first. Start from the beginning, marking values of each variable, and "execute" each line of code manually. Do this instead of regularly smashing the "run tests" button. You can certainly run tests blindly once, after you've written a complete solution, but don't do so repeat in quick succession. Walking through the code to catch errors earns you more brownie points that catching a bug after running the code. In short, whenever you fail a test case during practice, talk through test cases and explain the mistake. Treat it as though an interview had raised this edge case.
At a high-level, imagine you're a lecturer, lecturing yourself. Would you want an instructor to thinking about question silently? How would you feel if they coded half of the solution, then realized a problem and changed the algorithm? What if the instructor kept running the code, hitting errors, and make quick fixes without explaining?
Vocalizing your thoughts has a key advantage: Interviewers can correct you. In short, interviewers want you to succeed — it makes for a more interesting interview, and it's their role.
All of the above make lectures confusing; they also make it hard for interviewers to follow and help you. Note you don't need to be correct all the time. You just need to be clear about what you're doing and what you're thinking, at all times. Your interviewer will then guide you.
There's an unspoken structure once your interviewer writes and explains the question. Knowing this unspoken structure is extremely important, as it can save your interview and make you appear very prepared. Here's the structure you need to know:
- Interviewer poses question. Interviewer writes and explains questions, along with a test case.
- You ask questions. The interviewer invites you to ask questions. Even if they don't, your experience should suggest a few to ask.
- Discuss algorithm. Discuss your ideas and verbally design an algorithm with the interviewer.
- You code solution. Once your algorithm is correct, your interview will let you code up the solution.
- You test the code. You will need to verify your solution works, through a combination of "manual" code execution and writing/running tests.
- Interviewer extends the question. At this point, the interviewer may make the problem harder, or slightly change the question.
Let's now break down each of these steps in more detail, including what you should do at each of these stages of the coding interview.
Step 1. Interviewer poses question. Interviewer writes and explains questions, along with a test case. The written form of the question is not much different from questions you'll find online. Sometimes, the interviewer outright copies and pastes the question from an internal bank of coding questions.
Step 2. You ask questions. At this point, the interviewer invites you to ask questions. This is important: You should be asking questions to capture nuances of the question. Early on in your practice, you won't have many questions to ask. For me, I slowly learned which questions to ask year over year. It won't happen overnight, but you should work on asking questions from the below categories, starting with the easiest and working your way to the hardest to foresee:
Clarify inputs and outputs, or function. This is the most obvious category of questions. You can start off by simply rephrasing the prompt again, in your own words.
- Clarify the data types of your output. Ask if your inputs can have different data types. Are they always strings? Always integers? Are floats possible?
- On top of asking questions to clarify, you should also suggest new test cases. Suggest new inputs, and verify that the output you expect is the one the interviewer wants. During practice, you can try predicting outputs for a few new inputs, to expand your test suite.
Narrow or handle list of edge cases. Ask questions to clarify how your algorithm should respond to an edge case, or if you can ignore an edge case for now. Say you're asked to read from a file. The question sounds innocuous, but there are a ton of edge cases to be aware of.
- Ask how your function should behave if the file is empty, if the file handle is stale, or if the file is a symbolic link. These questions come from years of opening files in code and knowing what challenges your code will face. The earlier in your career you are, the fewer of these questions you're expected to come up with organically. During practice, pay attention to which edge cases your online coding puzzle tests.
- To add onto this, often times, your interviewer will ask you to come up with a reasonable expectation. Usually, any answer will work. For example, you may decide to return
Nonein all of the above cases. The most important part is that you recognized those cases to begin with.
Reduce complexity of the question. This is quite possibly the hardest category of questions to master. These are questions that change the problem trajectory significantly. This requires foresight and experience, to know that you can simplify the problem by making a few critical assumptions. Interviewers are delighted when you foresee where the question is going. Say we're again asked to read from a file.
- Ask for the maximum number of lines in your file or the length of the longest line. This shows that you understand memory constraints: This question could become more challenging if your file is too large to fit into RAM. If so, we need to understand how this impacts our algorithm: Do we load and process parts of the file at a time? Or, could we just ignore the problem and deny files that are too large?
- Ask if file locking guarantees your file is not written to while you're reading it. This shows that you understand concurrency issues: The question could also become more challenging if parts of the file were updated before you finished reading the file. If so, we need to understand the implication: Do we need to keep track of modification times? Or, could we just ignore the problem and accept that we may be processing stale data?
Step 3. Discuss algorithm. After you've exchanged questions with the interviewer, you should discuss your ideas and a possible algorithm with the interviewer.
- Keep the discussion verbal, without coding. Even though I push interviewees to discuss first, many candidates can't resist the temptation to begin coding immediately, despite my verbal plea. This is because of how they practiced: They practiced jumping straight into the code, as we discussed above.
- If you're completely unsure about how to tackle the problem, try a shotgun approach: Throw out random, seemingly relevant ideas. Your interviewer's facial expressions could help distinguish good from bad ideas. They may be more explicit with their guidance, either asking more questions or saying outright which idea you should pursue.
- During the interview, if your interviewer provides guidance, follow that advice. Your key to success is to let the interviewer guide you. Some more eager interviewers will immediately direct you towards the correct direction, if they hear a correct idea. Others may wait until you're out of ideas, then nudge you towards one of your existing ideas. Don't ignore these subtle social cues. Sometimes, your interviewer will start asking questions. Often times, if they're asking questions about a particular idea you had, they're trying to push you towards that idea. Other times, they're pointing out a flaw. Again, go with the flow.
Step 4. You code solution. Once your algorithm is correct, your interview will let you code up the solution.
- You don't need to explicitly ask the interviewer, "Is this algorithm correct?" Instead, you can ask, "Should I start coding this algorithm?" If the algorithm is wrong, interviewers will usually stop you and ask you to reconsider an edge case.
- As you code, explain your thought process. Don't just narrate your code verbatim. Explain that you're now checking for empty files or that you're now checking for odd numbers. During practice, you can practice explaining as you code, out loud. You don't even need a friend to practice with: You can additionally record yourself, and play back the recording to see how you should improve your explanations. It's cringey at first, but believe me, better for you to hear your first cringey explanation, than for an interviewer to hear it.
Step 5. You test the code. Once your solution is written, you will need to verify the correctness of your solution.
- Do not tell the interviewer, "I've finished the code" and leave it at that. Go back to the test case provided in the question, and make sure that test case passes. You get bonus points if you walk through the code and test case verbally first. During practice, practice manually executing your function line by line to see where your function goes wrong.
- If your code is broken, your interviewer will try to provide test cases that break your code. You again get bonus points if you recognize edge cases yourself, either by suggesting new test cases or by fixing the edge case, unprompted.
Step 6. Interviewer extends the question. At this point, the interviewer may make the problem harder, or slightly change the question. A good series of interview questions builds on top of one another. We return to step 1, for the extended question, and you repeat the same process.
In summary, prepare for the 4 stages of the coding question that you are responsible for: ask questions, discuss the algorithm, code, then test the code.
The bulk of this post focuses on pushing you to practice correctly. How you practice and the habits you build will make a world of difference in the interview. The name of the game, as we discussed, is two specific kinds of communication:
- Practice vocalizing your thoughts. Practice talking and thinking at the same time, as it's actually quite difficult. It's critical to think aloud, so that your interviewer can guide your thinking. The guidance is not always explicit, but be sure to pick up on social cues, so you can heed the interviewer's advice.
- Practice explaining as you code. Practice talking and coding at the same time, as this is also quite difficult. It's important to again keep your interviewer in the loop, so they can point out edge cases your code may or may not work for.
Now that you know how to practice, see these collections of question banks. Pick a question now to practice thinking and coding aloud:
- Cracking the Coding Interview2 book. This has been a staple of interview practice for a long time, since the first version's release in 2008. The latest edition was published in 2015 but is still highly recommended.
- leetcode, coderbyte, and interviewbit are more up-to-date question banks but the question topics remain the same. I used interviewbit myself when interviewing for internships, but leetcode is by far more popular today.
Granted, there are quite a few engineers that love a good puzzle. I certainly enjoy writing and solving riddles too, but the point still stands that riddle-solving isn't related to most engineering challenges. ↩
Disclosure: As an Amazon Associate I earn a small commission when readers make qualifying purchases. These help to keep the site running and come at no extra cost for your purchase. ↩
Got a question? Ask me on Twitter, at @lvinwan. Want more tips? Drop your email below, and I'll keep you in the loop.