Backend Coding Interview Prep

Tony Wu
10 min readOct 17, 2023

--

In this Medium post, we’ll describe strategies to prepare for coding interviews if you’re a backend engineer. We won’t rehash content that has been written before (for ex: here), but instead offer some new pointers and tips as you prepare for a coding interview for backend software engineers.

Preparation Stage

Selecting the Programming Language

It’s important to choose a good programming language as early as possible in preparation, so you do all of your practice problems with the given language. This will be difficult if Python is NOT your strongest language (otherwise you’ll choose Python).

If you’re a backend engineer but Python is not your strongest programming language (say you’re more experienced with Java, Rust, Scala, Go, etc.), my recommendation depends on if your interview is over a a Whiteboard (in-person) or over VC with an online IDE (e.g. Coderpad or HackerRank).

  1. If the interview is over the Whiteboard (in-person), then use Python.
  2. If the interview is over VC with an online IDE (e.g. Coderpad or HackerRank, etc.) then use the language you’re most familiar with.

Why? Several reasons:

  • In a whiteboard setting, a major limiting factor will be how fast you can write the code out physically with your hand and marker. In that settting, the shorter syntax of Python is really advantageous.
  • In a whiteboard setting, you’re not expected to have the perfect syntax and whether the code compiles/runs also is less important (it may even be difficult for the interviewer to tell if the code runs/is correct). therefore your potential lack of familiarity with Python is neutralized.
  • In an Online / Coderpad setting, you will be expected to have the code actually running and executing. If your code has syntax errors or you are unfamilar with details of the language (say Python), it’ll be extremely glaring.
  • In an Online / Coderpad setting, physically writing the code out will not be a limiting factor (since you’re typing), therefore the verboseness of other languages (C++, Java, Rust, etc.) relative to Python is not a big deal. Generally the following is true: (1) typing speed > (2) thinking speed > (3) hand-writing speed. Therefore Python’s conciseness as a language doesn’t give you much benefit.

For these reasons, I recommend backend candidates use the language they’re most familiar with if it’s online/VC/IDE interview and use Python if it’s a white boarding interview.

General skills to practice

Your success in a coding interview does depend on several different skills:

(1) Problem Understanding/Alignment: This is your skill of understanding the problem that is being asked of you and aligning with the interviewer over expectations.

  • How well do you ask questions to make sure you really grok the interview question and all the edge cases and nuances?
  • How well do you pick test cases to really test your problem understanding?
  • How well do you align with the interviewer on expectations (run-time, code complexity, what the solution looks like).

Note: one common mistake I see interviewees make is they fail to align with the interviewer on the type of solution that is expected.

(2) Problem Solving + Communication: Now that you understand the problem, how effective are you in coming up with a solution both in abstract as well as on paper and communicating it to the interviewer?

  • How well do you come up with a solution that works given the interviewer constraints/expectations?
  • How well do you communicate that solution to the interviewer as you’re implementing it, so they get signal on your problem-solving?

(3) Implementation: You now need to get code down into the whiteboard or IDE that matches your proposed solution.

  • How quickly and effortlessly are you able to get code down?
  • Do you display a mastery of the language you’ve chosen? Are you able to implement things the idiomatic way for the given language?

(4) Testing + Debugging: You need to then test and debug your code. This is a very different process if it’s on the whiteboard vs. over an online IDE.

  • How well do you come up with test cases that convince your interviewer your code is completely solid?
  • If there is a bug, how effectively do you find where the bug is?

Note: generally your debugging process will be much easier if you’ve broken down the problem into subroutines that you can test individually and have been testing each function incrementally as you develop it.

(5) Reflection on Solution (optional): Sometimes you’ll be asked to come up with O(n) for time and space and also reflect on how you’d make changes to your solution (e.g. I could make it faster if I used caching/memoization, etc.). Not every interview question will have this component, but that’s also a skill to develop.

How to do practice interviews

Doing practice coding interviews will be important. Try to find a friend who is also planning on interviewing and you can do practice interviews with each other. As you do the practice interviews, keep the following in mind:

  1. When practicing, don’t just focus on the outcome (did I write correct code or not) but also make sure that you exhibited all of the behaviors (e.g. aligning with the interviewer, setting up the right test cases, debugging thoughtfully).
  2. Try to video and screen record (with your practice partner’s permission) your interview. There are several products you can use (just Google them) to record both sides’ audio as well as what’s on the screen. Watch them back and study to see if you exhibited the correct behaviors.
  3. Practice the art of interviewer alignment. When watching back your coding interviews, check to see if you double-checked a few test cases with your interviewer to really understand the problem.
  4. Try to isolate which skills you need the most work on and have your practice partner test those skills in particular. For ex: if you are very good at (2) problem-solving/communication but are not as good at (3) testing/debugging, doing a bunch of practice problems where you don’t debug anything won’t be as useful in helping you improve.

General Types of Problems you will See

There are many different category of problems you might run into. Note a coding problem might involve one or multiple of these

(1) Building Custom Data Structures: The interviewer will ask you to come up with some type of custom data structure to solve a problem. Make sure you review your standard LinkedLists, HashMaps, Binary Trees and how to combine and mix them together to solve various problems.

(2) Binary Search: You may have to incorporate some form of binary search into your problem solving.

  • Examples: Leetcode 268

(3) String Manipulation: Get comfortable tokenizing and manipulating strings in ways to solve specific problems.

(4) Graph Traversal: Get experience identifying problems as graph problems and mapping the problem as some type of traversal on the graph or doing cycle detection, etc.

  • Examples: Leetcode 399

(5) Memoization: Memoization often fits as a “part 2” to an existing interview question. For example, you’ll be asked to solve some problem, and then apply memoization in order to make it more performant / tractable.

  • Examples: Leetcode 2623

(6) Using Stacks / Recursion:

What Not to Prepare

Knowing what not to prepare is likely just as valuable as knowing what to prepare. During your preparation, you don’t want to spend valuable time practicing problems that are highly unlikely to be asked of you during the interview.

(1) Leetcode Hard Problems: These generally don’t show up because they usually don’t provide much signal to the interviewer about your ability. Leetcode Hard problems tend to focus on pattern-matching some difficult algorithm to some problem type.

(2) Dynamic Programming: Generally, dynamic programming probably won’t be in your interview (or if it is, it would be the bonus solution for some question that you can solve some other way).

(3) Advanced Niche Algorithms: There’s a class of optimal algorithms that you study in Computer Science class that are probably not as useful to study.

  • For example, it’s unlikely that an interviewer will have you do a graph traversal that would require Dijkstra’s algorithm, when simple BFS/DFS/recursion would not suffice.
  • As another example, it’s unlikely the interviewer would ask you a problem where you’d have to do Linear Time Selection in O(n) when a much easier O(n log n) would not be acceptable.
  • If you ever run into one of these, and your interviewer is asking if you can do better than O(n log n ), you can always tell the interviewer, “I know there’s an O(n) solution based on Quicksort Linear Time Selection but I don’t remember the specific algorithm”.

During Interview

Once you are in the coding interview, there are some tips to increase your overall performance. These are not necessarily directly correlated with your core coding ability but are helpful interview tips.

Ask the interviewer how many questions

It’s a good idea to ask the interviewer how many questions and how many parts to each question they’d ideally like to get through during the session. The interviewer will usually tell you something like, “two questions, Question #1 has 2 parts and Question #2 has 1 part” or “only one question but it has 3 parts”.

Knowing this information is helpful for you as you pace/time your interview as it’ll give you signal if you’re falling behind or you’re ahead of time.

You’re ahead of time: If you’re ahead of time (for ex: the interviewer has told you there’s 2 parts to the problem and you’re already on part 2 with 30 min. to spare), then you can take less risk/variance.

  1. You’ll want to break down the problem into smaller functions, test each one thoroughly before moving onto the next question, etc.
  2. You can really thoroughly think through the design and syntax and make sure you’re writing really clean and solid code with great variable names, etc.

You’re behind on time: If you’re behind (for ex: there are three parts and you have ~15 min. remaining and still on part 1), then you want to increase the variance/risk. At this point you’re maybe looking to avoid a “Strong No Hire” and maybe at least salvage a “Weak No Hire” or “Weak Hire”.

  1. You’re more likely to ask for a hint to get you past whatever you’re stuck on so you can demonstrate positive signal for part 2, etc.
  2. You can take a higher risk strategy of trying to write out the code as quickly as possible, and skimp on testing each specific subroutine in order to get a working version.
  3. You might opt for trying a brute force solution that simply works rather than one that is more optimized.

Align with the interviewer on the constraints and a solution

Before you even write a single line of code, you should try to align with the interviewer if your solution is reasonable. Make sure you align on which edge cases/error conditions you’ll worry about. Some examples:

  • “I’m writing a brute force solution, is that okay with you?”
  • “I can implement this with memoization or without, which do you prefer?”
  • “Can I assume that the inputs won’t include negative numbers?”
  • “What happens if an entity points to itself in a cycle? Should I worry about this case?”

It’s important to stay disciplined and do this exercise during the interview even if you think the interview question being asked is trivial.

Break a large problem into smaller ones

Imagine as part of the coding interview, you’re asked to write a function to multiply two large numbers (say 100-digit numbers) together that are represented as int[] digits (since they don’t fit as 64-bit long integers).

private int[] multiply(int[] digits, int[] digits2);

Many candidates will try to write the code for this as one large function. However, this approach has two problems:

  1. The code within the function will be extremely long, which will be prone to mistakes. You’ll have to iterate with nested for loops, increasing the likelihood of off-by-one error or some other issue.
  2. It’ll be difficult for you to test different parts of the code and isolate where a potential bug/error is.

Instead you can abstract away the problem. Imagine if you have two functions: (1) that adds two large numbers (represented as int[] digits) and (2) that multiplies a single digit to a large number.

private List<Integer> add(List<Integer> digits1, List<Integer> digits2);
private List<Integer> multiply(List<Integer> digits1, int digit2);

Assuming these two functions existed, then the implementation for multiply becomes trivially easy:

private List<Integer> multiply(List<Integer> digits1, List<Integer> digits2) {
List<Integer> result = new ArrayList<Integer>(

for (int i = 0; i < digits2.length; i++) {
List<Integer> partialResult = multiply(digits, digits2.get(i));
for (int j = 0; j < i; j++) {
partialResult.add(0, 0);
}
result = add(result, partialResult);
}
return result;
}

From here you can then implement the subroutines add and multiply for single digits. This approach (breaking larger problem into smaller problem during the interview) offers several important advantages:

  1. You’re much less likely to make a mistake or a bug when each function you’re writing is much smaller.
  2. If you do have a bug, it becomes much easier to test and identify where the bug is. You can test each of the subroutines by themselves to make sure they’re working 100% and conclude that a bug might exist in the parent function.
  3. Saving implementation: In some cases (if you’re interviewing on a whiteboard) your interviewer might even decide it’s not worth having you implement the subroutines. In this case, the interviewer might decide that impelmenting add or multiply with single digits is extremely trivial and move onto coding question #2, etc. This would be a huge win, as you get full credit for solving the problem, even though you only had to write a fraction of the full solution.

Hint-Asking vs. Clarification

It’s okay to ask for hints, but the best interviewees are able to frame their “hints” as “clarification questions.” When you do this effectively, the interviewer doesn’t register you ask as “hint” but rather blames themselves for not providing a more clear question (or even gives you bonus points for checking edge cases!) There are several techniques/examples for how to do this:

  1. If you’re stuck or confused, try writing out some more test cases / examples and validating expectations.
  2. Stall for more time by validating trivial constraints with the interviewer (e.g. if the input is 0or null).
  3. You can often fish for a hint by simply acting confident and asking a clarifiying question. For example: “I know there’s a brute force solution, but I’m pretty sure there might be a more performant one — do you want me to search for that one, or just go with the brute force one?”

Additional Reading

For more pro-tips on preparing for a coding interview check out Cracking the Coding Interview.

--

--

Tony Wu

Director of Engineering. ex-FB, ex-Uber, ex-Twitter