Step 20 of 24

Coding interviews

Solve algorithm interview problems with a repeatable process, recognise the dozen patterns behind most questions, and communicate while you code.

19 min 9 sections

Most product companies — Gojek, Grab, Tokopedia, Shopee, and their peers worldwide — open their engineering interview loop with one or two coding rounds: 45–60 minutes, one or two algorithm problems, in a shared editor. You can find this format artificial and still pass it reliably, because it rewards a learnable skill: a structured process plus pattern recognition, done out loud. This lesson covers what interviewers actually score, a step-by-step method, the patterns behind most questions, a full worked example, and how to prepare without grinding a thousand problems. It builds on Data structures and Algorithms & complexity.

What's actually being assessed

A correct, optimal solution is not the whole score. A typical rubric covers four areas, and a candidate who reaches a near-optimal solution with excellent communication often beats one who silently types a perfect answer:

AreaWhat the interviewer looks for
Problem solvingClarifies the problem, finds a working approach, improves it, analyses complexity
CodingClean, idiomatic, correct code with good names and structure
VerificationTests their own code with examples and edge cases, finds and fixes bugs
CommunicationExplains thinking, takes hints well, collaborates

The interviewer is asking themselves: would I want to work through a hard problem with this person? Everything that follows is designed to make that answer yes.

A repeatable process

Use the same steps every time, so nerves have less room to derail you.

1. Understand (3–5 min). Restate the problem in your own words. Ask about input size, value ranges, duplicates, negative numbers, empty input, sortedness, and expected output for ties. Work through one example by hand. Interviewers often leave details ambiguous on purpose to see if you ask.

2. Match (1–2 min). Which pattern does this resemble? "Find a pair with a property" suggests a hash map or two pointers. "Contiguous subarray" suggests a sliding window or prefix sums. "Minimum steps" suggests BFS. The table below is your checklist.

3. Plan (5 min). State a brute-force solution and its complexity first — it proves you can solve it at all and gives you a baseline. Then improve it. Describe the optimised approach in plain words and get the interviewer's nod before coding. If they suggest a different direction, that's a hint; take it.

4. Implement (15–20 min). Write clean code, narrating as you go. Use descriptive names (left, seen, best rather than i, m, x). Extract helpers if a block gets complex. If you're unsure about a library call, say so and state your assumption.

5. Review and test (5 min). Don't say "I think it works." Walk through your code with a small example, tracking variable values line by line. Then try edge cases: empty input, one element, all duplicates, the largest values. Fix bugs calmly — finding your own bug scores points.

6. Evaluate (2 min). State time and space complexity, and mention trade-offs or follow-ups ("if the input didn't fit in memory, I'd…").

The patterns behind most problems

Most interview problems are variations on a small set of techniques. Learn to recognise the signal in the problem statement:

PatternSignal in the problemTypical complexity
Hash map / setfind pairs, duplicates, counts, "have we seen this?"O(n)
Two pointerssorted array, pairs/triples, palindromes, in-place partitioningO(n)
Sliding windowlongest/shortest contiguous subarray or substring with a propertyO(n)
Prefix sumsmany range-sum queries, "subarray sums to k"O(n)
Binary searchsorted input, or "smallest value that works"O(log n) per search
Stack (monotonic)matching brackets, "next greater element", histogram problemsO(n)
BFSshortest path in unweighted graph or grid, level orderO(V + E)
DFS / backtrackingexplore all paths, components, permutations, subsetsO(V + E) / exponential
Heaptop k, k-th largest, merge k sorted lists, schedulingO(n log k)
Intervalsoverlapping ranges, meeting rooms — sort by start firstO(n log n)
Dynamic programmingcount ways, min/max cost, "can you reach", overlapping subproblemsvaries, often O(n) or O(n²)
Union–finddynamic connectivity, grouping, cycle detection in undirected graphs~O(1) per operation

The concept notes on Big-O, hash tables, graph traversal and dynamic programming are quick refreshers before an interview.

A worked example

Given a string, return the length of the longest substring without repeating characters.

Understand. "Substring" means contiguous. You ask: what characters — ASCII or Unicode? (Assume bytes for now, say so.) Empty string? (Return 0.) Example: "abcabcbb" → "abc" → 3. "bbbbb" → 1. "pwwkew" → "wke" → 3.

Match. "Longest contiguous substring with a property" is the textbook sliding-window signal.

Plan. Brute force: check every substring for uniqueness — O(n³), or O(n²) with a set while extending. Better: keep a window [left, right] with no repeats. Extend right one character at a time. If the new character already appears inside the window, move left to just past its previous position. Track the last index of each character in a map. Each character enters and leaves the window at most once: O(n) time, O(k) space for k distinct characters.

Implement, narrating:

go
func LengthOfLongestSubstring(s string) int {
	lastSeen := make(map[byte]int) // character -> most recent index
	best, left := 0, 0
	for right := 0; right < len(s); right++ {
		if prev, ok := lastSeen[s[right]]; ok && prev >= left {
			left = prev + 1 // jump past the earlier copy
		}
		lastSeen[s[right]] = right
		best = max(best, right-left+1)
	}
	return best
}

Review. Trace "abba": a(0): window [0,0], best 1. b(1): [0,1], best 2. b(2): previous b at 1 ≥ left 0, so left = 2; window [2,2]. a(3): previous a at 0, but 0 < left 2, so it's outside the window and left stays 2; window [2,3], best stays 2. Correct — and that prev >= left check is the subtle bug most people miss. Mentioning why it's there is exactly what interviewers want to hear.

Evaluate. O(n) time, O(min(n, alphabet)) space. For Unicode, iterate over runes and key the map by rune while tracking byte or rune positions consistently.

Communicating under pressure

  • Think out loud, continuously. Silence for two minutes reads as "stuck" even when you're making progress. Narrate: "I'm considering a heap here because we need the smallest repeatedly…"
  • When stuck, say what you've tried and why it fails. Interviewers give hints to people whose thinking they can see.
  • Treat hints as collaboration, not failure. Taking a hint well is scored positively.
  • Don't fake it. If you don't know a library function, write a small helper or state the assumption.
  • Manage time. If 25 minutes in you only have a brute force, implement it cleanly and correctly, then discuss the optimisation. A working O(n²) beats a broken O(n).

Language and environment

Use the language you're fastest and most accurate in. Go is perfectly acceptable; know these by heart: slices.Sort, slices.SortFunc with cmp.Compare, sort.Search, strings.Builder, maps as sets (map[T]struct{}), slices as stacks and queues, container/heap (and how to write the five methods quickly), math.MaxInt, and the built-in min and max. Many shared editors don't have autocomplete; practise in a plain editor. If the company lets you run code, write a tiny main or test to check examples — but trace by hand first.

How to prepare efficiently

Grinding hundreds of random problems is slow. A better plan over 6–10 weeks:

  1. Refresh the fundamentals — the two foundation lessons of this roadmap.
  2. Study by pattern. For each pattern in the table, solve 5–8 problems, starting easy. After each, write one sentence: what signal should have told me which pattern to use?
  3. Mix them up. Once patterns feel familiar, solve unlabelled problems, so you practise the matching step.
  4. Time yourself. 25 minutes for a medium problem, including testing.
  5. Re-solve problems you failed a week later, from scratch. Spaced repetition beats volume.
  6. Do mock interviews with a friend or a peer platform, out loud. Communication is a separate skill from solving, and it only improves with practice in front of someone.

Around 100–150 well-understood problems across patterns is usually enough for most product-company interviews.

Practice

Solve this as you would in an interview, following all six steps, then compare with the solution:

Given a list of intervals [start, end], merge all overlapping intervals and return the result sorted by start. Example: [[1,3],[2,6],[8,10],[15,18]] → [[1,6],[8,10],[15,18]]. Intervals that touch ([1,4] and [4,5]) count as overlapping.

Show solution

Understand: ask whether the input is sorted (assume not), whether it can be empty (return empty), and confirm touching intervals merge (they do, per the statement).

Match: intervals — sort by start, then sweep.

Plan: brute force compares every pair repeatedly, O(n²) or worse. After sorting by start, any interval that overlaps the current merged interval must come immediately after it, so one pass suffices. O(n log n) for the sort, O(n) for the output.

go
func Merge(intervals [][2]int) [][2]int {
	if len(intervals) == 0 {
		return nil
	}
	sorted := slices.Clone(intervals) // don't mutate the caller's slice
	slices.SortFunc(sorted, func(a, b [2]int) int { return cmp.Compare(a[0], b[0]) })

	merged := [][2]int{sorted[0]}
	for _, cur := range sorted[1:] {
		last := &merged[len(merged)-1]
		if cur[0] <= last[1] { // overlaps or touches
			last[1] = max(last[1], cur[1])
		} else {
			merged = append(merged, cur)
		}
	}
	return merged
}

Review: trace the example: sorted is unchanged; [1,3] + [2,6] → [1,6]; [8,10] starts after 6 → new; [15,18] → new. Edge cases: one interval → returned as is; [[1,4],[2,3]] (contained) → max keeps 4, giving [1,4] — the classic bug is writing last[1] = cur[1], which would shrink it to 3; [[1,4],[4,5]] → <= merges to [1,5].

Taking &merged[len(merged)-1] is safe here because we only modify through the pointer before the next append; holding it across an append that reallocates would be a bug.

Evaluate: O(n log n) time, O(n) space for the sorted copy and output. If intervals arrived as a stream already sorted, it would be O(n) with O(1) extra space beyond the output.

Key takeaways

  • Interviewers score problem solving, code quality, self-testing and communication — not just the final answer.
  • Follow the same steps every time: understand, match a pattern, plan (brute force first), implement, test by hand, evaluate complexity.
  • Learn to spot the signal for each pattern: hash map, two pointers, sliding window, prefix sums, binary search, stacks, BFS/DFS, heaps, intervals, DP.
  • Think out loud, use hints, and prefer a clean working solution to a broken optimal one.
  • Prepare by pattern, re-solve failures, time yourself, and do mock interviews out loud.

Check yourself

Quiz

0/4 correct · 4 left

  1. 1.You have 10 minutes left and only a correct brute-force idea. What is the best move?

  2. 2.A problem asks for the shortest contiguous subarray whose sum is at least k, given only positive numbers. Which pattern fits best?

  3. 3.In the longest-substring solution, why does the code check prev >= left before moving left?

  4. 4.What is the most effective way to improve communication for coding interviews?

Concepts in this lesson

One-page notes on each idea, for review or a quick lookup later.

Finished reading?

Mark it complete to fill in your roadmap.