Skip to content

Senior Engineering Interview Handbook / Chapter 966

Appendix B - Coding Language Field Guides

A language-selection guide and standard-library reference for the operations, traps, and rehearsal habits that keep syntax from obscuring reasoning.

Choose the language that leaves room for reasoning

A syntax stall costs more than time. It interrupts the explanation, makes a simple data-structure choice look uncertain, and leaves less attention for the invariant and the tests. The best interview language is therefore the one in which ordinary moves have become ordinary.

First confirm that the interview platform accepts the language and supports the version and libraries you expect. Then ask a more demanding question: can you write a map, queue, heap, sort, parser, and small test harness without lookup—and explain their costs, mutation, equality, and ordering behavior? Familiarity from production work is useful, but it is not the same as recall under a short clock.

Choose one primary language. Keep a backup only when a target role or round creates a real need for it. Switching late is justified by a concrete constraint, such as platform support or an API-design exercise that strongly favors another language, not by the hope that different syntax will repair weak problem solving.

Five field guides

Each card is organized for exact lookup. Copy only the one for your chosen language, add the APIs you repeatedly forget, and remove anything you never use.

Python field guide

Need Common move
Frequency map collections.Counter or defaultdict(int)
Queue collections.deque
Heap heapq; use (priority, sequence, value) when equal priorities could expose non-comparable values
Sort by key items.sort(key=lambda x: ...) or sorted(items, key=...)
Binary search bisect_left, bisect_right
Large sentinel float("inf")

Repeated membership checks belong in a set, not a list. A list queue with pop(0) also pays to move the remaining elements; use deque.popleft(). Remember which operations mutate in place: list.sort() returns None, while sorted(...) returns a new list.

JavaScript field guide

Need Common move
Map new Map() instead of object when keys are not simple strings
Set new Set()
Array queue Maintain a head index; avoid repeated shift() for large queues
Sort numbers arr.sort((a, b) => a - b)
Character iteration for (const ch of s) iterates Unicode code points; it still does not segment user-perceived characters
Heap Bring a small tested heap class if the platform allows helper code

The default array sort converts values to strings, so numeric work needs a comparator. Use Map.has(key) to test presence when a stored value could be 0, false, or undefined. For a large queue, a head index avoids repeated shift() calls; compact the array if retained processed entries would matter in a longer-lived program.

Java field guide

Need Common move
Frequency map HashMap<K, Integer> with getOrDefault or merge
Queue ArrayDeque<T>
Heap PriorityQueue<T>
Sort arrays Arrays.sort(array)
Sort lists list.sort(comparator)
String builder StringBuilder for repeated concatenation

Primitive arrays and boxed collections have different APIs and equality behavior. Use Integer.compare(a, b) rather than a - b in a comparator when overflow is possible, and decide deliberately whether arithmetic needs long.

Go field guide

Need Common move
Frequency map map[T]int
Queue Slice plus head index
Heap Implement container/heap interface or use a prepared minimal heap pattern
Sort sort.Ints, sort.Slice
Set map[T]bool or map[T]struct{}
String building strings.Builder

Slices can share a backing array. Mutation through one slice may therefore be visible through another, while append may allocate a new backing array when capacity is exceeded. If isolation is part of correctness, make the copy explicit.

C++ field guide

Need Common move
Frequency map unordered_map<K, int>
Ordered map/set map, set
Queue/deque queue, deque
Heap priority_queue; use greater<T> for min-heap where suitable
Sort sort(v.begin(), v.end()) with comparator as needed
Binary search lower_bound, upper_bound

Iterator invalidation depends on the container and operation; do not carry one rule across vector, ordered associative containers, and unordered containers. A comparator must define a strict weak ordering. Also watch values silently converted between signed sizes and unsigned container indices.

Three small traps with large consequences

The language should support the reasoning, but a language-specific default can quietly change the answer. These three examples are worth being able to write and explain from memory.

JavaScript numeric sort

const nums = [10, 2, 1];
nums.sort((a, b) => a - b); // [1, 2, 10]

Without the comparator, the values are compared as strings. An interval, greedy, or binary-search solution can then fail while the sorting call still looks plausible.

Queue in Python

from collections import deque

q = deque([start])
while q:
    node = q.popleft()
    for nxt in graph[node]:
        if nxt not in seen:
            seen.add(nxt)
            q.append(nxt)

Using pop(0) on a list makes every removal shift the remaining elements. The algorithm may still be correct, but its implementation no longer has the queue cost the explanation claims.

Priority in Java

PriorityQueue<int[]> pq = new PriorityQueue<>(
    (a, b) -> Integer.compare(a[0], b[0])
);
pq.add(new int[] {distance, node});

Integer.compare states the ordering directly and avoids the overflow risk of subtracting one priority from the other.

Turn the reference into fluency

Do not memorize this appendix wholesale. Build a one-page card from code you have run. A useful rehearsal takes one familiar problem and changes the language burden while keeping the algorithm steady:

  1. Write the map, set, queue, heap, sort, and binary-search operations without lookup.
  2. Implement the problem and state the invariant before the main loop.
  3. Add empty, singleton, duplicate, and boundary cases that fit that problem; do not add irrelevant tests by ritual.
  4. Explain which operations mutate, which may copy or alias, and what each important operation costs.
  5. Reopen the documentation, correct the card, then repeat once without it.

The mistakes from that run belong on the card. A copied catalogue of APIs does not reveal where your recall actually fails.

Use this short sequence before a coding loop:

collections -> sorting -> heap/queue -> strings -> parsing -> tests -> complexity
confirm platform -> name the structure -> state its cost -> show the invariant -> test the boundary

Keep the explanation language-aware but not language-obsessed. Name the behavior that affects the solution: operation cost, mutation, aliasing, equality, ordering, overflow, or text representation. If a helper becomes noisy, simplify it and make its contract explicit. The reader of the code should still be able to see the algorithm.