interviewpath
  • 0day streak
  • 10total XP
  • Level 1

Focus mode

Coding fluency and standard-library costs

Read alongside

Python documentation: costs of built-in types and the container modules: Time complexity of operations on built-in types

Official CPython costs for list, dict, set and str; read with the collections, heapq and bisect pages if Python is your interview language.

Objectives

  • Choose the right built-in type in your interview language for a stack, FIFO queue, deque, hash map, hash set, ordered map and min- or max-heap, and state each operation’s cost.
  • Identify operations that look cheap but are linear: front insertion or removal on arrays, slicing, membership tests on lists, and string concatenation in loops.
  • Write a correct custom sort order (key function or comparator) including descending order and tie-breaking, and state whether your sort is stable.
  • Avoid your language’s traps: aliasing of nested lists or slices, boxed-integer equality, iterator invalidation, integer overflow and recursion limits.
  • Use the library priority queue for max-heap behavior and for payloads that are not comparable.
  • Produce a one-page cheat sheet of costs and idioms for one language, checked against its official documentation.

Why it matters

A coding interview leaves little time, so the language has to disappear: you should not be looking up how to build a max-heap or whether a sort is stable. Fluency also means knowing what library calls cost. A BFS that uses a plain array as its queue, or a loop that rebuilds a string on every step, turns an O(n) idea into O(n²) code, and interviewers notice. Pick one interview language and know its standard library precisely; the rest of this note lists the facts that matter most for algorithmic code in five common choices.

Core ideas

For each abstract structure (stack, FIFO queue, deque, hash map and set, ordered map, priority queue, sort with a custom order) know the concrete type you will use, its costs, and the traps.

Python. list is a dynamic array: append and pop() are amortized O(1), but pop(0) and insert(0, x) shift every element (O(n)), x in lst scans the list, and slicing copies. Use collections.deque for queues. Strings are immutable, so build them with ''.join(parts); the documentation warns that repeated concatenation can be quadratic. dict preserves insertion order (guaranteed since 3.7). heapq is a min-heap over a list: negate numeric keys for max-heap behavior (Python 3.14 added _max variants), and put a counter in tuples so ties never compare payloads. There is no balanced BST in the standard library: bisect searches a sorted list in O(log n) but inserts in O(n). Sorts are stable. CPython's recursion limit is typically 1000 frames. [[0] * m] * n creates n references to one row.

C++. vector::push_back is amortized O(1), but a reallocation invalidates every iterator, pointer and reference into the vector; call reserve when the size is known. unordered_map is average O(1), a rehash invalidates its iterators, and operator[] inserts missing keys, so test membership with find, count or contains (C++20). map and set are ordered (usually red-black trees) with O(log n) member lower_bound; the free std::lower_bound on their iterators takes linear steps. priority_queue is a max-heap; use std::greater<T> for a min-heap. std::sort is O(n log n), not stable, and requires a strict weak ordering: a <= comparator is undefined behavior. Signed overflow is undefined, so use long long and lo + (hi - lo) / 2.

Java. PriorityQueue is a min-heap by natural order; for a max-heap pass Comparator.reverseOrder(), compare with Integer.compare rather than subtraction (which can overflow), and remember that remove(Object) and contains are linear and iteration is not in priority order. Collections hold boxed values: == on two Integer objects compares references and may pass for small cached values, then fail. HashMap iteration order is unspecified; LinkedHashMap keeps insertion order and TreeMap offers floorKey and ceilingKey in O(log n). Use ArrayDeque for stacks and queues. Object sorts are stable; primitive sorts use a dual-pivot quicksort. int overflow wraps silently.

Go. A slice is a view (pointer, length, capacity) onto a backing array. append writes into spare capacity, so slices cut from the same array can overwrite each other: copy a slice before storing it, for example a backtracking path. Map iteration order is unspecified and can differ between loops; sort the keys when order matters. Sets are map[T]struct{}. Heaps come from container/heap, which you drive through an interface and which offers Fix for priority changes. sort.Search is binary search over a monotone predicate; sort.Slice is not stable, sort.SliceStable is.

JavaScript and TypeScript. sort() without a comparator compares elements as strings, so [10, 9, 1].sort() yields [1, 10, 9]; pass (a, b) => a - b for numbers. Sorting has been stable since ES2019. shift and unshift re-index the whole array, so BFS queues need a head index. Map keeps insertion order, accepts any key type and has size; plain objects coerce keys to strings. Map and Set compare object keys by identity, so encode a coordinate as a string or a number. Numbers are doubles, exact up to 2⁵³ − 1 (BigInt beyond), and bitwise operators work on 32-bit integers. There is no built-in heap, deque or ordered map.

Common misconceptions

  • "An array is a fine queue." Removing from the front moves every remaining element in Python lists and Java ArrayList, and JavaScript's shift() is specified the same way; use a deque or a moving head index.
  • "The default sort does what I mean." JavaScript compares numbers as strings, C++ std::sort is unstable, and a comparator that is not a consistent ordering breaks sorting in every language.
  • "Heaps are min-heaps everywhere." Python and Java default to min-heaps, C++ to a max-heap, and JavaScript has none.
  • "Copies happen when I expect them." Python slices and C++ pass-by-value copy in O(n), while Go re-slicing, Python [[0] * m] * n and JavaScript Array(n).fill([]) share storage and cause aliasing bugs.
  • "Hash map iteration order is stable." Python dict, JavaScript Map and Java LinkedHashMap promise insertion order; Go maps and Java HashMap do not.

How to approach it

Write a one-page cheat sheet for your language from its official documentation: each structure, its costs and three traps. Drill the idioms you use most (frequency count, BFS queue, heap with tuple priorities, two-key sort, iterative DFS) until they take seconds. In the interview, mention costs as you call library functions ("a deque, so popleft is O(1)"). Among the languages a role allows, interviewers care less about which one you pick than about code that fights it.

Self-check before you finish

  1. Which type do you use for a FIFO queue, and what does removing from the front cost?
  2. Is your language’s default priority queue a min-heap or a max-heap, and how do you reverse it?
  3. Is your standard sort stable, and what happens with an inconsistent comparator?
  4. How do you use a pair such as a grid coordinate as a hash key in your language?
  5. What is your recursion or stack limit, and how do you avoid hitting it?
  6. Which operations copy data implicitly, and which share storage?