Create your own
Lesson illustration

A Repeatable Workflow for Solving Coding Interview Problems

Hello, and welcome to the first lesson in your coding-interview preparation course. The early modules build the habits needed for Java algorithm interviews; later modules extend those habits to system design, distributed systems, and technical-lead interview scenarios relevant to roles at companies such as Google or Walmart.

A coding interview is not only a test of whether you eventually produce working code. It is also an observation of how you handle an ambiguous request, make trade-offs, communicate uncertainty, and validate your work. This lesson gives you a repeatable workflow for doing that under time pressure: clarify, model, solve, and test.

The framework below is a useful visual memory aid. Its “Plan” and “Optimize” stages are the heart of what this lesson calls model and solve.

A five-stage interview workflow: clarify the prompt, plan an approach, optimize through explicit trade-offs, write code while narrating, and test with an example plus an edge case.

The purpose of a workflow

The most common weak start to a coding interview is immediate coding: the candidate hears a familiar word such as “array,” recognizes a pattern, and starts typing. That can lock them into the wrong interpretation before they have established what the interviewer actually wants.

A workflow protects against this. It gives you a visible, professional sequence even when the algorithm is not immediately obvious:

  1. Clarify the problem contract.
  2. Model the problem with examples, constraints, and a simple baseline.
  3. Solve by choosing and explaining an approach.
  4. Test by tracing the completed code deliberately.

You will still need to learn data structures and patterns. But a good framework ensures that you demonstrate useful reasoning even before the key insight appears.

Last-minute coding interview prep - IGotAnOffer

Read the coding-interview framework and its worked “Two Sum” example from IGotAnOffer. It is a concise demonstration of how a candidate can make their reasoning visible rather than silently jumping to code.

In Section 4.1, “Coding interview answer framework,” read the complete five-step framework. Then continue to Section 4.2, “Sample answer,” and read the Two Sum walkthrough. Notice the short spoken statements used at each stage, especially the assumptions made before selecting an algorithm.

The resource labels the middle stages “brute force” and “optimize.” In this course, treat those as two parts of model and solve:

  • Model: turn informal words into a precise contract and a small concrete representation of the problem.
  • Solve: present a correct baseline, then select the best approach supported by the constraints.

This distinction matters. You cannot reliably choose a solution until you know the output contract, input limits, and permitted assumptions.


1. Clarify: establish the contract before solving

Suppose an interviewer says:

“Given an array of integers and a target, return the indices of two numbers that add up to the target.”

A strong candidate does not need to ask every conceivable question. Ask questions that could change the algorithm, return value, or correctness criteria.

Start by restating the task:

“Let me restate it: given an integer array and a target, I need to return the indices of two distinct elements whose values sum to that target.”

This does three things at once:

  • verifies your interpretation;
  • makes an implicit rule, “distinct elements,” explicit;
  • gives the interviewer a natural opportunity to correct you.

Then ask focused questions. For this prompt, useful questions are:

AreaQuestionWhy it matters
Solution existence“Can I assume exactly one valid pair exists?”Determines what to return if no pair exists and whether you must choose among multiple pairs.
Element reuse“May the same array element be used twice?”Affects whether one value can satisfy the target by itself.
Output format“Should I return indices in any order?”Prevents correct values in an unacceptable representation.
Input bounds“What is the largest possible array size?”Helps rule out solutions that will be too slow.
Value range“May values be negative or duplicated?”Prevents assumptions based on positive or unique numbers.
Mutation“May I modify or sort the input array?”Sorting can simplify some approaches but may violate the contract or lose original indices.

Do not perform clarifying questions mechanically. If the prompt already explicitly says “exactly one answer” and “do not use the same element twice,” acknowledge those constraints and move on.

For our worked version, assume the interviewer answers:

  • The array contains integers, including negatives and duplicates.
  • There is exactly one valid pair.
  • One element cannot be reused.
  • Return the two indices in any order.
  • The array may be large, so an approach better than quadratic time is desirable.
  • Do not modify the array.

Now summarize the agreement aloud:

“Great. I will return the indices of two different elements, there is exactly one valid answer, duplicates are allowed, and I should preserve the input array.”

That is the contract. Coding before you can state it clearly is premature.


2. Model: use examples, constraints, and a baseline

A model is a compact representation that lets you reason about a problem rather than merely stare at its wording. Build it in three layers.

Layer 1: a normal example

Write a tiny input-output table before choosing data structures:

numstargetExpected result
[2, 7, 11, 15]9[0, 1]

At index , the value is . The value needed to reach is . That needed value is called the complement:

This equation is a useful model of the entire problem. Instead of repeatedly asking, “Which pair sums to the target?”, we ask, “For this value, have I already seen its complement?”

Layer 2: edge examples

Examples reveal ambiguities and likely bugs early. Before coding, write cases that pressure the assumptions:

CaseInputExpected resultWhat it checks
Minimal valid input[4, 5], target 9[0, 1]Two elements are enough.
Duplicate values[3, 3], target 6[0, 1]Equal values may form a pair, but they must occupy different indices.
Negative values[-4, 10, 6], target 2[0, 2]Complements may be positive or negative.
Pair later in array[8, 1, 4, 6], target 10[2, 3]The solution is not necessarily near the beginning.

These are not merely final checks. They influence the algorithm. For example, [3, 3] shows why a solution must distinguish a value from an occurrence of that value at a particular index.

Layer 3: expected scale

At this stage, translate a vague performance statement into a preliminary constraint:

“Since the input can be large, checking every possible pair may not be acceptable. I’ll first describe that baseline, then look for a way to avoid repeating work.”

You will derive time and space complexity more formally in the next lesson. For now, recognize the practical consequence: an approach with two loops that compare pairs grows much faster than a single pass through the array.

Whiteboard Coding Interviews: 6 Steps to Solve Any Problem

Watch “Whiteboard Coding Interviews: 6 Steps to Solve Any Problem” by Fullstack Academy for a compact demonstration of why restating, writing examples, explaining an approach, and tracing code should happen before and after implementation.

Watch restating for the role of paraphrasing the prompt and resolving ambiguity. Then watch examples and method; focus on the input-output table and on narrating an intended strategy before implementation. Finally, watch manual testing to see how a deliberate trace demonstrates correctness.


3. Solve: move from a correct baseline to a justified choice

Start with the brute-force solution

For Two Sum, the baseline is straightforward:

  1. Choose the first index.
  2. Compare its value with every later index.
  3. If a pair sums to the target, return the two indices.

This examines every possible pair exactly once. It is easy to explain and easy to verify. Its time cost is , because for each of roughly positions, it may inspect roughly other positions. It uses extra space.

Even when it is too slow, state it. Doing so proves you have a correctness anchor and allows the interviewer to follow your optimization.

A clear spoken version is:

“The simplest correct approach is to check every pair with nested loops. It uses constant extra space, but takes quadratic time, so I would not choose it for a large input.”

Identify repeated work

The brute-force method repeatedly scans for a complement. When considering a current value , it asks whether some earlier value equals . Rather than rescan the earlier portion of the array each time, store information about values already encountered.

A Java HashMap<Integer, Integer> can store:

  • key: a number previously seen;
  • value: that number’s index.

The key invariant is:

At the start of each iteration, seen maps every earlier value encountered to an index where it occurred.

When processing index :

  1. Compute the complement.
  2. Check whether the complement is already in seen.
  3. If it is, the stored index and form a valid pair.
  4. Otherwise, store the current number and its index, then continue.

Checking before storing is important. It guarantees that an element cannot match with itself at the same index. It also handles [3, 3] correctly: the first 3 is stored; the second finds that earlier 3.

State the trade-off and choose

The optimized approach makes one pass through the array. Under the usual expected-performance assumption for a hash map, lookup and insertion are constant time on average. The result is:

The trade-off is simple: use additional memory to eliminate repeated scans.

Say that explicitly:

“I can trade linear extra space for linear expected time by storing each previously seen value and index in a hash map. I will check for the complement before inserting the current element, which prevents reuse of the same index.”

This is better than declaring, “I’ll use a hash map,” without explaining what the map represents or why its update order is correct.


4. Code: implement the chosen model in Java

Only after the contract, examples, baseline, and selected approach are visible should you write Java.

import java.util.HashMap;
import java.util.Map;

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> seen = new HashMap<>();

    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];

        if (seen.containsKey(complement)) {
            return new int[] { seen.get(complement), i };
        }

        seen.put(nums[i], i);
    }

    return new int[0];
}

Narrate the code at the level of the algorithm, not every punctuation mark:

“I create a map from a number to its earlier index. For each position, I compute the needed complement. If that complement has already appeared, I return its saved index and the current index. Otherwise I record the current number for later positions.”

A few implementation decisions deserve attention:

  • nums.length is the Java array length.
  • seen.get(complement) retrieves the earlier index stored for the complement.
  • new int[] { ... } creates the returned pair of indices.
  • The final return new int[0] is defensive. Under the agreed contract of exactly one valid answer, execution never reaches it. In a real interview, use the behavior the interviewer specifies for “no solution.”

Do not narrate in a way that hides uncertainty. If you need a moment, say what you are checking:

“I’m verifying that I look up the complement before inserting the current value, so the same element cannot be used twice.”

That kind of narration is focused and useful. It is very different from filling silence with every keystroke.


5. Test: prove to yourself that the code matches the contract

Testing is not saying, “It should work.” It is executing the algorithm against examples that target particular risks.

Start with the normal case, [2, 7, 11, 15] with target 9.

IterationiCurrent valueComplementseen before checkResult
First027{}Store 2: 0
Second172{2: 0}Find 2; return [0, 1]

Notice how this trace checks the invariant. Before processing index , the map contains only the earlier index . Therefore retrieving index is safe and valid.

Then test an edge case specifically chosen to expose a common defect:

InputTargetCritical trace
[3, 3]6At index 0, complement 3 is absent, so store 3:0. At index 1, complement 3 is present, so return [0,1].

If you had inserted first and checked second, an incorrect implementation might match index with itself. The order of operations is therefore not stylistic; it is part of the correctness argument.

Finish your interview response with a short verification statement:

“I traced the standard case and the duplicate-value edge case. The map contains only earlier elements at each step, so the algorithm never reuses the current index. The solution is expected time and extra space.”

For coding interviews, a reliable final checklist is:

  • Did I return the required type and format?
  • Did I honor all stated assumptions?
  • Did I trace at least one ordinary example?
  • Did I test an input that pressures a boundary or special condition?
  • Did I state time and space costs?
  • Did I remain in conversation rather than silently coding?

A compact interview script

You do not need to recite a rigid formula. But until the workflow becomes automatic, this sequence is worth rehearsing aloud:

“I’ll first confirm the requirements. We need indices of two distinct values that sum to the target; may I assume exactly one pair and preserve the input?”

“For a quick example, [2, 7, 11, 15] with target 9 returns [0, 1]. I also want to account for duplicates such as [3, 3].”

“The direct solution checks every pair, which is quadratic time. To avoid rescanning, I can store each earlier value and its index in a hash map.”

“For each number, I calculate the complement and look for it before storing the current value. That ordering prevents using an element twice.”

“I’ll now trace the normal case and then [3, 3] to verify the duplicate-value behavior.”

The aim is not sounding memorized. The aim is having a dependable internal structure, so your conversation remains clear when the problem is unfamiliar.


Key takeaways

A coding interview answer should be a visible chain of reasoning, not a race to type.

  • Clarify the contract: inputs, outputs, assumptions, constraints, and mutation rules.
  • Model the problem with small examples, edge cases, and a baseline method.
  • Solve by explaining the baseline, identifying repeated work, choosing a data structure or algorithm, and stating the trade-off.
  • Test by manually tracing ordinary and adversarial examples against the actual code.
  • Keep the interviewer involved with concise statements of intent, invariants, and decisions.

Next, you will make the complexity statements used here precise: how to derive the time and space complexity of Java code with sequential and nested loops.

Can't find a good explanation? Sign up and we'll make it for you

Sign up