How to Crack the Coding Interview: The 7 Phases of Interview Prep
Preparing for Coding Interviews can seem long and complicated when there is no clear path for studying or measuring your progress. This article attempts to build a clear roadmap such that anyone can interview prep thoughtfully and carefully over a period of 2–3 months or less. When I was interview prepping, it started off as doing random problems and slowly learning different concepts. I used to always give the age-old advice of “practice more problems” for anyone that needed help. In hindsight, these were the actual steps I took to get 3 offers from FAANGMULA, and avoid the hassle of random “leetcode grinding”.
Here is a TikTok summarizing this article, but read on for more value + detail.
🧑💻 ↔️ 👩💻 Phase 1) Understand the Interview Process: From Both Perspectives
I like to view these interviews as a bit of a game. Before you succeed in any game, we have to understand the rules and criteria to win. This step is simple, and starts with the following questions:
“How does the interviewer judge my performance to make a Hire VS No-Hire Decision?”
“What skills should be displayed in the interview to satisfy the Interviewer?”
“How do I effectively practice those skills before the game starts?”
Most candidates cannot answer the above questions. This lack of understanding leads to the general frustration behind Coding Interviews being seen as “broken”.
This also leads to another assumption: “To pass the interview, you need the absolute optimal answer and flawless code”. This is simply not true.
These assumptions and frustrations are put on full display when a candidate is rejected, and they immediately think it’s purely based on optimality of their solution. This can be a factor but it is not the single deciding factor.
Lack of understanding also leads to endless “leetcode grinding”. Solving a lot of algorithm questions is beneficial but not satisfactory. I have spoken with candidates that have practiced 200+ questions, yet still fail interviews consistently. Why is this the case? There is a disconnect between an online platform like LeetCode saying your solution “passed”, and an interviewer’s methodology of assessing a Hire VS No-Hire decision.
If a candidate does extremely well in multiple interviews with multiple job offers, that does not imply the same candidate would be highly ranked in an online platform. How is that possible? Because successful candidates understand the interview process far better than how to win a Competitive Programming contest.
The goal is to understand the interview process as BOTH a Candidate & Interviewer. Let’s forget everything we know about solving loads of problems online, and understand what skills interviewers are measuring. Take a look at this simplified general rubric used by the interviewer.
Notice how every candidate’s aim of getting the optimal answer is only captured by the Problem Solving section. Which means this alone is not sufficient for passing with a “Hire” decision. There is still weight on Communication, Technical Competency, and Testing. With knowledge on the criteria is for a Strong Hire Decision, let’s dive into how to prep for all 4 factors. You can read about this rubric in more detail at The Tech Interview Handbook.
For more info on interview expectations by company, check out Cracking the Coding Interview by Gayle Lock McDowell and Elements of Programming Interviews.
📖 Phase 2) Review Data Structures
The key at this phase is to understand the Pros VS Cons per data structure. Let’s start with which data structures are relevant:
- Arrays, Lists, Strings
- Linked Lists, Stacks, Queues
- Hash Maps, Hash Sets
- Heaps, Sorted Maps/Sets
- Trees, Graphs
The Pros VS Cons for each can be determined by the following:
- Time Complexity for Operations: Search, Add, Update, Delete.
- Space Complexity for Storing Elements and Relevant Ordering.
You can then contextualize when to use one data structure over another, which improves Problem Solving. For example, HashMaps are great for operations with O(1) Time Complexity and pairing unique keys to values. There is no particular ordering or sorted-ness to these key/value pairs. Heaps are great at maintaining elements in sorted order, but adding and removing the next element takes O(log(n)) Time.
Therefore, any problem that requires values to be sorted should remind us of Heaps. If instead we need quick lookups, consider using HashMaps. You instantly have an intuition for which data structures may be relevant to the problem being solved.
How do I fully understand and remember this for EVERY Data Structure? 😑
Most would suggest reading about how they work under the hood, and that is a necessary step. I prefer to aim for long-term retention instead of a quick “memorize and forget” approach. Most likely you will interview multiple times throughout your career and re-use this material.
What’s more practical is implementing them from scratch in the language of your choice. For example, create a Linked List Class that allows for searching, adding, and deleting elements. Re-use your code to build your own version of a Stack. Do it again to implement a Queue. Now implement a Doubly Linked List. Tada! You have implemented 4 data structures without any existing implementations.
This provides a clear understanding of the Time and Space Complexities for all 4 operations: search, add, update, delete. As a bonus, some interviewers will flat out ask, “How do HashMaps search in O(1) Time”. I call this, Data Structure Trivia, since you either know it or you don’t. These are trivial questions once this phase is complete.
🧠 Phase 3) Practice Algorithmic Thinking
Now you are equipped to start practicing some coding questions, and the data structures will serve as your toolkit. Here’s a list of Online Coding Platforms I used along the way.
- LeetCode
- CodeSignal
- Codility
- HackerRank
In total you have thousands of questions to choose from but who has time for that? Fortunately, interviewers across many companies stick to a dozen or so topics. Which site you use is nowhere near as important as the problems practiced themselves. Here’s a list of topics sorted from Easiest to Hardest (in my opinion).
- Two Pointers
- Binary Search
- Sliding Window
- Fast + Slow Pointers
- Sorting
- Merging Intervals
- Linked List Reversal
- BFS
- Recursion
- DFS
- Topological Sort
- Memoization
- DP
To be fair, the list is actually longer because some topics have nested sub-topics. Sorting consists of different algorithms like: Bubble Sort, Merge Sort, Quick Sort, Heap Sort, Bucket Sort, etc. By filtering questions on these high level topics we can learn each of the sub-topics along the way. Memoization and DP are at the absolute bottom since they are so rarely asked and the most challenging for most candidates.
For each category, target attempting 10 questions composed of 3 Easy and 7 Medium. There’s no need to worry about Hard problems initially until Mediums seem fairly easy.
You can also rely on different lists online like Blind 75, Grind 75, LeetCode 100, and NeetCode 150. These lists are fairly similar and based on the same topics, so don’t think too hard on which list to do. Just get started.
⚡️ Phase 4) Grasping Patterns & Concepts
Pattern Recognition can make Coding Interviews twice as easy.
The goal of this phase is to improve [Problem Solving + Coding] Speed. It’s great that over time your skills are improving, but speed is crucial. This is necessary since interviews often last 40 minutes or less.
First, we can pattern match the type of question to instantly categorize it against one of many data structures or algorithms from the prior phases. Then after choosing the appropriate algorithm, we can pattern match the implementation to code it out quickly.
When I see the need to traverse a grid-like maze, I can recall this fits the category of Graph problems. Boom, data structure identified. A more obvious case is when I have to traverse a Graph or Tree. Then I wonder which algorithms are appropriate, and recall that BFS and DFS are viable for searching Graphs. Finally, I compare how each algorithm performs in Time and Space Complexity to finally choose one. Writing the code does not take very long since BFS + DFS do not have very many ways to implement them.
How do I improve Pattern Recognition for Problem Solving and Coding?
Problem Solving: Take note of the inputs and the wording for each problem. Over time you will realize similar problems rely on similar answers.
Here are some examples:
- If it mentions finding some connection/path between 2 locations, we can pattern match to a Graph question. Graphs can be solved with BFS or DFS. If it focuses on finding any path, you can go with either BFS or DFS. I would prefer DFS since it is recursive, which implies less lines of code to be written. If there is an emphasis on finding the shortest path, then pick BFS for optimal performance since DFS will be sub-optimal. Ideally we want to visit each node only once to achieve a Time & Space Complexity of O(N). If the graph contains cycles, we must avoid re-visiting nodes by using a Visited Set. If the graph has weighted edges, Dijkstra is needed for finding the Shortest Paths.
- If we need to find the longest/shortest sub-string/array that fulfills a criteria, then Sliding Window may be the answer. To keep track of the start and end of your window, you will need two pointers or indices. Keeping track of the exact values within your window can be done with a Hash Map/Set. There must be a condition to either extend the window on the right side, or decrease the side from the left side. This leads to an algorithm with O(N) Time & Space Complexity.
Coding: Since similar problems rely on the same set of algorithms, you often re-write the same code. To improve your coding speed, implement each algorithm in your language of choice. Then when you attempt to solve a problem and run into errors, quickly reference these templates and course-correct. After multiple repetitions, implementation speed will increase and you will not reference these templates as often. Coding the same algorithms will become a habit requiring very little thought.
High-Level Study Habits to maintain during this phase:
- Set a timer for 30 minutes while solving, and spend another 30+ minutes understanding the solution.
- Aim for 1–3 Easy problems a day, and aim for Mediums after Week 1–2.
- Track problems in a spreadsheet and categorize them by Data Structure & Algorithm.
- Re-visit 1 Week old questions assuming you do not recall the solutions.
- Produce your own 3 Test Cases to work on the Testing Criteria of the Coding Interview rubric.
- Focus on comprehending solutions, not memorization.
🥋 Phase 5) Simulate via Mock Interviews
The interview can be super nerve-racking. It’s a completely different setting from solving problems alone in silence. You have no idea how the interviewer is going to introduce themselves, what questions they’ll ask, or how they will react as you try to solve their technical questions. I used to overthink and wonder, “What do they think about my answer so far” and “Am I typing too slowly? They must think I’m unqualified”. This is what I like to call, Interview Anxiety.
How do I get rid of Interview Anxiety?
Put yourself in an interview setting 1–2X a week via Mock Interviews. You can do this thru platforms like Pramp & InterviewingIO. Many candidates, from self-taught, to new grads, and even gainfully employed engineers will leverage these platforms to practice interviewing as a skill. Some of the mock interviewers can be very helpful in guiding you, while others are more quiet and leave you to think for yourself. This is great experience for meeting different types of interviewer personalities.
It’s also great for networking with folks that are also on the job hunt. But I never found it useful for learning new algorithms and data structures, since it can take 1+ hrs. to grasp a new concept. Over time, you will not be concerned about the interviewer’s opinion as you struggle to solve questions. You will be mentally focused on attacking the problem presented and overthink less. You will learn how to communicate your thought process to multiple interviewers.
Consider how you present yourself to the interviewer by sitting in their seat.
There is arguably more value added when you act the interviewer, because you can observe any flaws in the candidate. This goes hand in hand with “Phase 1) Understand the Interview Process from Both Perspectives”.
For example, I noticed many candidates do not ask clarifying questions about the problem. This observation led me to consider whether I make the same mistake in my actual interviews. You are effectively learning from other people’s mistakes, and making sure to avoid them yourself. The main skills you will observe go back to the Coding Interview Rubric mentioned at the start: Communication, Problem Solving, Technical Competency, and Testing.
👂 Phase 6) Feedback & Self-Reflect
With every Mock Interview, analyze the rating you receive for the 4 Criteria on the rubric. Most candidates do a reasonable job at Communication, but struggle with the rest. Problem Solving has to be the most difficult criteria to meet, since it helps find and compare multiple solutions. With a reasonable solution, we can proceed to start Coding and Testing. Otherwise, poor Problem Solving puts the candidate’s progress to a halt and it’s difficult to starting Coding without any approach..
Analyze the following to properly self-reflect:
- Do I fully clarify the problem from the start of the interview?
- Did I fail any unexpected test cases and could I have thought of them beforhand?
- How much time do I spend trying to Problem Solve? How much is spent on Coding? Which step took the longest?
- Which categories of problems are the most difficult to Problem Solve? Maybe it’s time to revisit them.
- Which algorithms do I struggle to Code? Perhaps I do not fully understand them and need to review.
- Did I provide multiple solutions from brute force to optimal?
- Can I explain the Time & Space Complexity of any solutions?
- Out of the 4 criteria from the Coding Interview Rubric, where was most of my time spent during the mock interview?
- What is the consistent negative & positive feedback received over multiple interviews?
- How can I think about this new problem differently to come to the same solution faster?
These questions will help you focus on your weaknesses and what problems to re-visit for review. With each and every mock interview, you’ll notice less mistakes being made because you are cognizant of the initial mistakes and took action to improve them. This is also why mock interviews should not be done daily, because time is needed to improve on mistakes.
Without proper self-reflection and analysis, you may find little to no improvement in mock interviews over the long term. This will lead to frustration and a sense of unfairness. Which is why this is critical to the final phase.
🥊 Phase 7) Interview for Technical Roles
This phase is essentially a combination of the 5th + 6th phases, but this time real offers are at stake. The goal is not to necessarily pass the interview process, but to see how far we can get given the amount of time spent prepping. This means passing the Online Assessment, Technical Phone Screen, and finally a panel of interviewers during the On-Site (which may be virtual).
Irrespective of how good or bad these rounds go, take note of the questions being asked, the answers you provide, and all follow up questions. After the interview, review and see if there was a better answer you could have provided. If you receive a rejection, most definitely the only factor you can improve on is the quality of your answers. This is fully in your control to improve on. Ignore the interviewer’s demeanor if they were having a bad day, because that is always outside of your control.
Compare your performance against the Coding Interview Rubric. This should be a fairly easy task since you’ve been self-reflecting for weeks over many mock interviews and making adjustments. Simply repeat this process and make new adjustments in between each round of the interview. Implement these new adjustments in Mock Interviews to prepare for the next technical role.
Last thing to note, pay attention to any nuance in the way each company conducts their interviews. Culture has an impact on the way interviewers interact with candidates and the types of questions being tested.
For example, Meta asks 2 Medium level questions per round which leads to very little small talk and a greater focus on problem solving and coding speed. Some of their questions may not have super intuitive answers like, Next Permutation. But they do not shy away from asking interview questions that have been exposed online.
Meanwhile, Microsoft asks less challenging questions that are more popular/known. From my experience, Microsoft Engineers are more sociable in treating candidates like teammates and stick to easier concepts like HashMaps and Linked Lists.
Amazon has a a greater focus on Behavioral questions (a.k.a. Leadership Principles) and so technical skills alone are insufficient. Amazon Engineers are more willing to disagree and challenge candidates on answers provided.
Over time you will recognize slight differences in the way companies perform interviews. Of course, these comparisons are anecdotal based on my experience. Be sure to draw these comparisons yourself.
If the recruiter sends you a rejection, ask for feedback. Most likely, none will be provided since you can sue over discriminatory hiring practices. However, every now and then one recruiter is willing to help you out.
Sometimes it can just be a numbers game. You can be a terrible candidate with 1/10 chance of receiving an offer, but if 20 companies reach out then that offer is bound to come soon. On the other hand, if you hardly get contacted for roles, you have to be more analytical about where you are performing well and what needs improvement to get a high success rate over few opportunities.
🏆 Celebrate the Offers 💰
All of these phases may seem over the top, time consuming, and difficult. I believe it is all worth it when you can receive not just 1 or 2 but 3+ offers. At this stage, companies have to appeal to the candidate for a signature on the dotted line, which means you can negotiate compensation.
The only thing to to keep in mind is this will not be the last time you go through these 7 phases. The company you join may not have a rigorous engineering culture, or maybe the project work is uninteresting. You can always leave for any number of reasons, and the company can perform mass lay-offs.
Every now and then, you will find a post on Reddit or Blind from a Senior Software Engineer that wants to leave their workplace without sacrificing their compensation. But they have no motivation to go through the interview process as they’ve forgotten many of the concepts learned. They are essentially stuck at their employer. The point is you do not want to be that person. View this interview process as a game that hardly changes over time. What I mean is, a Binary Search question today will probably repeat itself again in a few years with some slight re-wording. The same Data Structures and Algorithms are static.
The 7 Phases are inescapable. Over time, technical interviews will include Object Oriented Design, System Design, and Behavioral/Leadership especially when you interview for higher levels.
Ultimately the interview prep process is the same: Learn the Game, Practice the Problems, Interview & Reflect, Repeat.