Here is a scenario that plays out in thousands of coding interviews every day: a candidate sees a problem, immediately starts typing, gets halfway through, realizes their approach does not work, panics, tries to salvage it, runs out of time, and leaves defeated.
The frustrating part? They probably knew enough to solve the problem. What they lacked was not knowledge but a systematic approach.
This chapter gives you that approach. A framework you can apply to any problem, whether you are practicing on LeetCode, interviewing at Google, or debugging production code at 2 AM. The techniques here will not just help you solve more problems. They will help you solve them faster, with fewer bugs, and with the confidence that comes from knowing exactly what to do next.
When you face a new problem, your brain has two modes it can operate in. The first is pattern matching: you recognize the problem as similar to something you have solved before, and the solution flows naturally. This is the goal of learning DSA patterns, and it works beautifully when it works.
But what happens when you do not recognize the pattern? What happens when the problem is genuinely new, or when interview pressure makes your mind go blank? This is where most people fail. Without a systematic approach, they either freeze or start coding randomly, hoping something will work.
A framework gives you a fallback. It turns "I have no idea what to do" into "Let me work through my process." Even when you are stuck, you know the next step. This alone reduces anxiety and improves performance.
The framework we will learn has five phases: Understand, Match, Plan, Implement, and Verify. Let us go through each one in detail.
The biggest mistake candidates make is starting to code before they fully understand what they are solving. This seems obvious, but under time pressure, the urge to "get started" is powerful. Resist it.
Problem statements are carefully written. Every word matters. Read the entire problem at least twice before doing anything else. Pay attention to:
In an interview, you are expected to ask questions. Interviewers intentionally leave some details ambiguous to see if you will clarify. Here are questions you should always consider:
| Category | Example Questions |
|---|---|
| Input | Can the array be empty? Can it contain negative numbers? Are there duplicates? |
| Output | If there are multiple valid answers, can I return any of them? What should I return if no solution exists? |
| Constraints | What is the maximum size of the input? Do I need to handle very large numbers? |
| Format | Is the input sorted? Is the tree a BST or any binary tree? Is the graph directed or undirected? |
Even on LeetCode, mentally ask these questions. The constraints section usually answers them, but developing this habit prepares you for interviews.
Before thinking about solutions, make sure you understand the problem by tracing through the given examples manually. Then create your own examples, especially:
Let us apply this to a real problem.
Problem: Two Sum
Given an array of integers nums and an integer target, return the indices of two numbers that add up to target. You may assume each input has exactly one solution, and you may not use the same element twice.
Understanding checklist:
Tracing examples:
Now I truly understand what the problem is asking.
Once you understand the problem, the next step is to see if it matches any patterns you know. This is where your study of DSA patterns pays off. You are not starting from scratch. You are searching your mental library for similar problems.
Ask yourself these questions to identify potential approaches:
| Question | Suggests |
|---|---|
| Am I looking for a pair/triplet that satisfies a condition? | Two pointers, hash map |
| Am I looking for a contiguous subarray? | Sliding window, prefix sum |
| Is the input sorted, or would sorting help? | Binary search, two pointers |
| Do I need to explore all possibilities? | Backtracking, BFS/DFS |
| Does the problem have optimal substructure? | Dynamic programming, greedy |
| Am I working with a tree or graph? | BFS, DFS, tree traversal |
| Do I need O(1) lookup? | Hash map, hash set |
| Do I need to track frequency/count? | Hash map |
| Am I looking for top K or Kth element? | Heap, quickselect |
| Does the problem involve intervals? | Sorting + greedy, merge intervals |
Over time, you will build a mental map connecting problem characteristics to approaches:
Sometimes you genuinely do not recognize the pattern. That is okay. Fall back to first principles:
For Two Sum, the brute force is checking every pair: O(n²). The bottleneck is that for each number, we scan the entire array to find its complement. The insight is that we can use a hash map to check for the complement in O(1), giving us O(n) overall.
Now comes the critical phase that many people skip: planning. Before writing any code, you should have a clear, step-by-step plan that you could explain to someone else.
Do not write actual code yet. Write out the logic in plain English or pseudocode. This forces you to think through the algorithm without getting distracted by syntax.
Two Sum Plan:
Before coding, trace through your plan with a concrete example. This catches logical errors early.
The plan works. Now you can code with confidence.
Before implementing, think about edge cases:
If your plan does not handle an edge case, modify it now rather than debugging later.
In an interview, explain your plan before coding. Say something like:
"I am going to use a hash map approach. As I iterate through the array, for each number I will check if its complement exists in the map. If yes, I have found my answer. If not, I add the current number to the map. This gives me O(n) time and O(n) space. Does this approach sound reasonable?"
This accomplishes several things:
Now, finally, you can write code. But even here, there are techniques to write cleaner code faster with fewer bugs.
Write the function signature and return statement first. This ensures your code compiles and establishes the structure.
Your pseudocode becomes your guide. Translate each step into code:
Your code should read like your plan. Avoid single letters for anything but loop indices:
| Bad | Good |
|---|---|
m | map or numToIndex |
c | complement |
t | target |
n | nums or numbers |
In interviews, readability matters. The interviewer is reading your code in real time.
If there are edge cases that need special handling, put them at the top of your function:
| Mistake | Prevention |
|---|---|
| Off-by-one errors | Double-check loop bounds: < length vs <= length |
| Null pointer exceptions | Check for null before accessing |
| Integer overflow | Use long for intermediate calculations if needed |
| Modifying while iterating | Use index-based loop or create a copy |
| Wrong return type | Check the function signature |
You have written the code. Before declaring victory, verify it works.
Run through the provided examples manually or with actual test cases:
Create tests for the edge cases you identified:
If something fails, do not just stare at the code. Trace through it step by step with the failing input:
Always be ready to state the complexity of your solution:
In interviews, state this proactively:
"The time complexity is O(n) because we iterate through the array once, and each hash map operation is O(1). The space complexity is O(n) because in the worst case, we store all n elements in the hash map before finding the answer."
Here is the complete framework in one view:
A typical coding interview is 45-60 minutes. Here is how to allocate that time:
| Phase | Time | Activities |
|---|---|---|
| Understand | 5-7 min | Read, ask questions, work examples |
| Match + Plan | 5-10 min | Identify approach, write pseudocode, communicate |
| Implement | 15-20 min | Write clean, working code |
| Verify | 5-10 min | Test, debug, analyze complexity |
| Buffer | 5-10 min | Follow-up questions, optimization discussion |
Common time mistakes:
If you are running low on time, communicate:
"I realize I am running short on time. Let me quickly describe how I would handle this edge case, and then walk you through the complexity analysis."
Let us apply the entire framework to a new problem.
Problem: Valid Parentheses
Given a string s containing just the characters (, ), {, }, [ and ], determine if the input string is valid. A string is valid if:
Reading carefully:
Clarifying questions:
([{}])? (Valid per the rules)([)]? (Invalid, wrong order)Working examples:
Pattern recognition:
Key insight: When I see an open bracket, I push it. When I see a close bracket, I check if the top of the stack is the matching open bracket. If not, invalid. At the end, the stack should be empty.
Walk through with example:
Test given examples:
Test edge cases:
Complexity analysis:
((((().| Mistake | Symptom | Prevention |
|---|---|---|
| Not understanding the problem | Wrong approach entirely | Spend more time in Phase 1, ask questions |
| Jumping to code | Getting stuck halfway, rewriting | Always plan before implementing |
| Ignoring constraints | TLE (Time Limit Exceeded) | Check constraints, know what complexity you need |
| Not testing | Wrong answer on edge cases | Always verify with examples and edge cases |
| Poor communication | Interviewer cannot follow | Explain your thinking out loud |
| Overcomplicating | Convoluted code, bugs | Start simple, optimize if needed |
| Giving up too early | Not solving solvable problems | Stick to the framework, stay calm |
The framework becomes second nature with practice. Here is how to train:
Keep a log of problems you solve:
| Date | Problem | Pattern Used | Solved Alone? | Time | Notes |
|---|---|---|---|---|---|
| 1/15 | Two Sum | Hash map | Yes | 12 min | Complement lookup pattern |
| 1/15 | Valid Parentheses | Stack | Yes | 18 min | LIFO for matching pairs |
| 1/16 | 3Sum | Two pointers | Hint needed | 35 min | Sort first, then two pointers |
This helps you identify weak areas and track improvement.
Q1: Why should you spend time understanding and planning before coding?
Spending time on understanding and planning prevents wasted effort and reduces bugs. If you misunderstand the problem, you might solve the wrong thing entirely. If you start coding without a plan, you often get stuck halfway through and have to restart. The few minutes invested in understanding and planning save many more minutes of debugging and rewriting. In interviews, this also demonstrates to the interviewer that you think before you act, which is a valuable engineering trait.
Q2: What should you do if you do not recognize the pattern for a problem?
Start with brute force. Ask yourself: what is the simplest solution that would work if efficiency did not matter? Often this means trying all possibilities, nested loops, or recursion that explores every path. Once you have a brute force solution, identify its bottleneck. What makes it slow? Are you recalculating something repeatedly? Is there redundant work? This analysis often reveals the optimization. Additionally, look at the constraints to understand what time complexity you need, which narrows down possible approaches.
Q3: How should you handle edge cases in your solution?
First, identify edge cases during the Understand phase by asking questions like: Can the input be empty? Can values be negative? Are there duplicates? Then, during the Plan phase, ensure your algorithm handles these cases, either through the main logic or explicit checks. During Implementation, add explicit edge case handling at the top of your function when needed. Finally, during Verify, test your code with edge cases to confirm they work. It is much easier to handle edge cases proactively than to debug them later.
Q4: How should you manage your time in a 45-minute coding interview?
Allocate roughly 5-7 minutes to understand the problem and ask clarifying questions, 5-10 minutes to identify your approach and explain your plan, 15-20 minutes to implement your solution, and 5-10 minutes to test and verify. Keep some buffer for discussion. If you are running low on time, communicate with the interviewer. It is better to have working code for the main cases with a verbal explanation of edge case handling than to have incomplete code that handles everything. Avoid spending too long on any single phase.
Q5: What should you do if your code has a bug during an interview?
Stay calm and systematic. First, identify which test case fails. Then trace through your code line by line with that specific input, writing down variable values at each step. Compare what actually happens to what you expected. The bug is where reality diverges from expectation. Common culprits are off-by-one errors in loop bounds, incorrect conditional logic, or forgetting to handle a specific case. If time is short, explain to the interviewer what you think the bug is and how you would fix it, even if you do not have time to implement the fix.
This chapter gave you a systematic framework for solving coding problems:
The framework feels slow at first, but with practice it becomes automatic. The structure gives you confidence: even when you do not immediately see the answer, you know what to do next.
In the next chapter, we will cover Recursion Fundamentals. Recursion is the foundation for many DSA topics including trees, graphs, backtracking, and dynamic programming. Mastering recursive thinking early will make everything else easier.