Data structures & algorithms
Everything you need to reason about data structures and algorithms the way coding interviews demand: complexity analysis, the core structures, the algorithm families built on them, and the recurring problem-solving patterns. Interviewers lean on DSA because it shows how you model a problem, weigh trade-offs, and defend the efficiency of your solution under pressure.
on this pageshowhide
guide
overview
~2 minData structures and algorithms is the subject most coding rounds are built on. The interviewer hands you a problem and watches three things: how you turn the prose into a model (a sequence, a set of pairs, a graph), which structure you pick to hold that model, and whether you can defend the cost of the result in time and space. A working answer matters; explaining why it is correct and why it is fast enough matters as much, and at senior levels it usually matters more. The subject splits into four layers. The first is the measuring stick: [complexity analysis](/topics/found-dsa-complexity), the notation and reasoning every other section uses to state a cost. The second is the structures themselves: [arrays and strings](/topics/found-dsa-arrays-strings), linked lists, stacks and queues, [hash tables](/topics/found-dsa-hash-tables), trees, heaps and graphs, each defined by the operations it makes cheap and the ones it makes expensive. The third is the algorithm families that run on them: sorting, binary search, recursion and backtracking, [dynamic programming](/topics/found-dsa-dynamic-programming), greedy choice, and the bit-level and number-theory toolkit. The fourth is the layer candidates skip and interviewers weigh: the recurring [problem patterns](/topics/found-dsa-algo-patterns) such as two pointers and sliding windows, and the [problem-solving strategy](/topics/found-dsa-problem-solving) that shapes what you say in the first five minutes. Learn complexity first, because every later answer ends with a cost you have to justify. Then work through arrays, hashing and the linear structures, since most problems start there; trees and graphs next, because that is where recursion stops being optional; the paradigms and patterns last, once you can recognise the structures they operate on. Questions run from a junior asking why an operation is constant time to a principal asked what a guarantee actually promises and when it breaks. The same idea often appears at several depths, so come back to a section as your level rises rather than treating it as finished.
primer
A handful of ideas carry the whole subject. With these solid, most questions below become applications rather than facts to memorise. - **Cost is a growth rate, not a stopwatch reading.** Asymptotic notation describes how work scales as input grows, which is why it hides constant factors and why two algorithms with the same bound can still differ noticeably in practice. Every answer should end with a time bound and a space bound, and you should know whether each is worst case, expected or amortized. Those are three different promises, and interviewers check which one you mean. - **A structure is a bundle of operation costs.** Arrays buy constant-time positional access with contiguous memory and pay for it when inserting in the middle. Linked structures buy cheap splicing and pay for it on access. Hashing buys expected constant-time lookup by key and gives up order. Balanced trees keep order at a logarithmic price. Choosing a structure means naming the operation the problem repeats most and picking whatever makes that one cheap. - **Invariants make algorithms correct.** A heap's parent-to-child ordering, a search tree's ordering across whole subtrees, binary search's shrinking candidate range, a sliding window's validity condition: each is a property you establish, preserve at every step and rely on at the end. Interviewers probe the invariant because a candidate who can state it can usually repair a broken implementation. - **Recursion is the shared engine.** Tree walks, graph search, divide and conquer, backtracking and top-down dynamic programming are the same machinery (a base case, progress toward it, a combining step) pointed at different problems. A clear picture of the call stack pays off in every one of those sections. - **Repeated work is the thing to remove.** Most optimisations eliminate recomputation: storing results of subproblems that recur, updating a running quantity instead of rebuilding it, remembering what has already been seen in a set or map. When a brute force is too slow, first ask what it computes more than once. - **Constraints predict the intended solution.** The input sizes and limits in a problem statement indicate roughly which complexity class is expected, and so which families of approach are worth considering. Reading them before designing is a skill, not a trick.
- Asymptotic notation
- The bounds (big-O above, big-Omega below, big-Theta tight) that describe how cost grows with input size, setting aside constant factors and smaller terms.
- Worst-case complexity
- The cost bound over the most expensive input of a given size; the reading an interviewer assumes unless you say expected or amortized.
- Expected complexity
- Cost averaged over a distribution of inputs or over an algorithm's own random choices. Hash lookups and randomized quicksort are normally quoted this way.
- Amortized cost
- Average cost per operation across any sequence of operations, letting a rare expensive step be spread over many cheap ones with no probability assumption.
- Auxiliary space
- Memory used beyond the input itself, recursion stack included; what claims of working in place or in constant space normally refer to.
- Invariant
- A property that holds before and after every step of an algorithm or every operation on a structure, used both to argue correctness and to locate bugs.
- Load factor
- The ratio of stored entries to buckets in a hash table; crossing a chosen threshold triggers a resize that keeps expected lookup cost constant.
- Collision
- Two distinct keys landing in the same bucket. Every hash table has them; the resolution scheme, chaining or open addressing, decides what they cost.
- Heap property
- The ordering rule a binary heap keeps between each parent and its children, which puts the minimum or maximum at the root without sorting the rest.
- Balanced search tree
- A search tree whose height is held logarithmic in its size by rotations or splits, so ordered operations stay logarithmic whatever the insertion order.
- Adjacency list
- A graph representation storing each vertex's neighbours; its space grows with vertices plus edges, which suits the sparse graphs most problems describe.
- Topological order
- A linear ordering of a directed graph's vertices in which every edge points forward; one exists exactly when the graph has no cycle.
- Overlapping subproblems
- The condition dynamic programming exploits: a recursive decomposition reaches the same smaller problem many times, so storing each result once removes the repetition.
- Optimal substructure
- An optimal solution is assembled from optimal solutions to its subproblems. Dynamic programming and greedy algorithms both rely on it; greedy also needs a provably safe local choice.
- Stable sort
- A sort that keeps elements with equal keys in their original relative order, which matters when sorting by one key and then another.
- Backtracking
- Depth-first construction of candidate solutions that abandons a partial candidate as soon as it cannot lead to a valid one.
The sections are not independent chapters; they lean on each other in a fairly fixed order. **Complexity analysis is the common language.** Every other section states its results in it, and several are best read as worked examples of one technique: dynamic arrays and hash-table resizing illustrate amortized cost, recursive sorts illustrate recurrences, and hashing illustrates the gap between expected and worst-case bounds. **The linear structures are building blocks.** Stacks and queues are implemented on top of arrays or linked nodes, and they return as the frontier of graph traversal: a queue for breadth-first search, a stack or the call stack for depth-first. A hash table paired with a doubly linked list gives a cache with an eviction order, and a binary heap is an array read as a tree. **Trees sit between lists and graphs.** A tree is a connected graph with no cycles and a chosen root, so tree traversals are the simple case of graph traversal; the extra bookkeeping graphs need comes from cycles and shared paths. Search trees are also what you reach for when a hash table's lack of order becomes the problem. **The paradigms are ways of organising a search.** Brute force enumerates candidates; backtracking enumerates them while pruning dead branches; divide and conquer splits the input and combines the results; dynamic programming notices that subproblems overlap and stores them; greedy commits to one choice per step and needs a proof that it never has to reconsider. Many interview discussions are really about which of these a problem admits, and the sections on [greedy algorithms](/topics/found-dsa-greedy) and [dynamic programming](/topics/found-dsa-dynamic-programming) both spend time on the boundary between the two. **Sorting and searching are infrastructure.** Sorting is often a preprocessing step that turns a harder problem into a linear scan, and binary search applies wherever a monotone yes-or-no condition exists, over a sorted array or over a range of candidate answers. **Patterns and strategy sit on top.** Two pointers, sliding windows, prefix sums and monotonic stacks are compact recipes that pair a structure with an invariant, and they only make sense once the structures are familiar. [Problem-solving strategy](/topics/found-dsa-problem-solving) then ties everything to the round itself: clarifying the task, stating a baseline, choosing a target complexity from the constraints, and narrating the trade-off you made.
- Complexity Analysis →
Every answer ends with a time and space bound, so learn to derive and state one before studying the things it measures.
- Arrays & Strings →
Most problems arrive as an array or a string, and their memory layout sets the costs every other structure is compared against.
- Hashing & Hash Tables →
The usual tool for turning a quadratic search into a linear one, and a structure whose guarantees candidates routinely overstate.
- Recursion & Backtracking →
Trees, graphs, divide and conquer and dynamic programming all assume a working model of recursive calls; build it before them.
- Trees →
Recursion applied to a real structure: traversals, the search-tree invariant, why balancing matters, and the step up to graphs.
- Interview Problem Patterns →
With the structures familiar, the patterns show how a structure and an invariant combine to solve whole families of problems.
Stating a complexity without saying whether it is worst case, expected or amortized; hash lookups and dynamic-array appends are where this gets challenged.
Quoting logarithmic lookup for a binary search tree without mentioning balance; built from already-ordered input, an unbalanced tree degrades into a chain.
Leaving the recursion stack out of a space bound: a recursive solution with no explicit allocation still uses memory proportional to its depth.
Hunting for the clever solution in silence instead of stating a correct brute force first; the interviewer cannot credit an approach they never heard.
Accepting a greedy rule because it passes the examples, with no exchange argument and no search for a counterexample; greedy failures are silent.
Binary search boundary slips: mixing inclusive and exclusive bounds, a loop condition that never terminates, or a midpoint computation that overflows fixed-width integers.
Treating a graph like a tree and skipping visited-tracking, which loops on cycles or expands shared vertices many times.
Picking a structure by habit rather than by the operation the problem repeats; the right choice starts from which operation has to be cheap.
Comparing floating-point results for exact equality, or ignoring integer overflow on sums and products near the type's limit.
The same few choices recur across nearly every section, and naming the one you are making is often worth more than the code. - **Time versus space.** Most speed-ups spend memory: a set of seen values, a memo table, a precomputed prefix array. Say what you spent and whether the constraints allow it; sometimes the expected answer is the slower, constant-space version. - **Worst case versus typical case.** Quicksort, hash tables and unbalanced search trees are fast in the common case and slow on adversarial input. Whether that matters depends on who controls the input, and an interviewer may ask exactly that. - **Order versus lookup speed.** Hashing gives up ordering for expected constant-time access; a balanced tree or a sorted array keeps range queries and nearest neighbours available at a logarithmic price. - **Preprocessing versus per-query cost.** Sorting once, building prefix sums or an index pays upfront so that many later queries are cheap. It is a good trade when queries are many and the data rarely changes, and a poor one for a single query. - **Asymptotic bound versus constant factors.** Contiguous memory, cache behaviour and small inputs can make the theoretically slower option faster in practice, which is why many hybrid library sorts hand short ranges to insertion sort. - **Clarity versus cleverness.** Recursion is often clearer and iteration safer against deep stacks; a bit trick is compact but harder to verify. In a round, prefer the version you can explain and test.
Some shapes appear across many sections under different names; recognising them is how you place an unfamiliar problem quickly. - **Shrink the candidate set.** Binary search on sorted data, binary search over a range of possible answers, and two pointers converging on a sorted array all discard part of the search space per step using a monotone condition. - **Maintain a running summary.** Sliding windows, prefix sums, running extremes and furthest-reach counters keep a small piece of state updated per element instead of rescanning. - **Expand a frontier.** Breadth-first search, depth-first search, Dijkstra's algorithm and level-order traversal differ mainly in which container holds the frontier: a queue, a stack or a priority queue. - **Choose, recurse, undo.** Subsets, permutations, combinations and constraint puzzles share one backtracking skeleton; problems differ in the choice set and the pruning rule. - **Define a state and a transition.** Dynamic programming problems on grids, knapsacks, sequences and intervals yield once you can say what a table cell means and which smaller cells it reads. - **Keep the best k.** A heap capped at k elements answers top-k and k-way merge questions in a single pass. - **Merge groups as you go.** Union-find tracks connectivity as edges arrive and underlies cycle detection in undirected graphs and Kruskal's spanning-tree algorithm. The [pattern and structure selection](/topics/found-dsa-algo-patterns-selection) section works the reverse direction: from a problem statement to the pattern it hides.
explore
- Complexity Analysis56 questions
- Asymptotic Notation & Bounds16 questions
- Analyzing Iterative Code8 questions
- Analyzing Recursive Code12 questions
- Amortized Analysis8 questions
- Space Complexity8 questions
- Constraints-to-Complexity Reasoning4 questions
- Arrays & Strings59 questions
- Static Arrays10 questions
- Dynamic Arrays8 questions
- Matrices & 2D Arrays8 questions
- String Representation & Memory12 questions
- String Algorithms13 questions
- In-Place Manipulation8 questions
- Linked Lists43 questions
- Fundamentals & Memory Model16 questions
- Core Pointer Operations20 questions
- Tradeoffs & Practical Use7 questions
- Stacks & Queues34 questions
- Stacks9 questions
- Queues8 questions
- Deques4 questions
- Ring Buffers4 questions
- Implementation Strategies9 questions
- Hashing & Hash Tables65 questions
- Hash Functions & Key Design12 questions
- Collision Resolution12 questions
- Load Factor & Resizing8 questions
- Hash Maps & Sets in Practice8 questions
- Guarantees & Pitfalls12 questions
- Alternatives & Cousins13 questions
- Trees55 questions
- Binary Trees8 questions
- Binary Search Trees8 questions
- Self-Balancing Trees8 questions
- Tries (Prefix Trees)4 questions
- Suffix Trees & Arrays4 questions
- Disk & Range-Query Trees9 questions
- General Tree Algorithms14 questions
- Heaps & Priority Queues43 questions
- Heap Mechanics13 questions
- Priority Queue APIs8 questions
- Canonical Heap Patterns18 questions
- Heap Variants: d-ary, Indexed, Fibonacci4 questions
- Graphs & Traversal52 questions
- Representations & Modeling8 questions
- BFS & DFS Traversal8 questions
- Union-Find (DSU)5 questions
- DAGs & Topological Sort5 questions
- Shortest Paths14 questions
- Minimum Spanning Trees4 questions
- Special Graph Classes8 questions
- Sorting63 questions
- Elementary Sorts9 questions
- Efficient Comparison Sorts13 questions
- Non-Comparison Sorts13 questions
- Properties & Theory7 questions
- Hybrid & Library Sorts9 questions
- Sorting in Practice12 questions
- Searching & Binary Search57 questions
- Baseline Search & Preconditions8 questions
- Core Binary Search8 questions
- Boundary Variants8 questions
- Binary Search on the Answer8 questions
- Rotated & Modified Inputs13 questions
- Exotic Search Variants12 questions
- Recursion & Backtracking50 questions
- Recursion Mechanics12 questions
- Recursion vs Iteration8 questions
- Divide & Conquer9 questions
- Backtracking Framework8 questions
- Canonical Backtracking Families13 questions
- Dynamic Programming61 questions
- Recognizing DP Problems8 questions
- Implementation Approaches16 questions
- Problem Archetypes37 questions
- Greedy Algorithms28 questions
- Greedy Principles & Correctness8 questions
- Greedy vs. Dynamic Programming4 questions
- Canonical Greedy Problem Families12 questions
- Greedy Inside Classic Algorithms4 questions
- Interview Problem Patterns (has its own guide)85 questions
- Two Pointers12 questions
- Sliding Window11 questions
- Fast & Slow Pointers8 questions
- Interval Techniques12 questions
- Prefix Sums & Difference Arrays13 questions
- Monotonic Stacks & Queues12 questions
- Pattern & Structure Selection9 questions
- Cyclic Sort4 questions
- Randomized Techniques4 questions
- Bit Manipulation & Math47 questions
- Bitwise Fundamentals12 questions
- XOR Techniques5 questions
- Bitmasks as Sets & State5 questions
- Number Theory Essentials12 questions
- Factorials & Combinations4 questions
- Numeric Edge Cases9 questions
- Problem-Solving Strategy (has its own guide)35 questions
- Structured Solving Method12 questions
- Constraint-Driven Planning3 questions
- Study Plans & Curated Lists4 questions
- Deliberate Practice Technique12 questions
- Round Formats & Expectations4 questions
→ has its own guide
- AI & Data Scientistroleanchors this topic
- AI Engineerroleanchors this topic
- AI Red Teamingroleanchors this topic
- Android Developerroleanchors this topic
- Backend Developerroleanchors this topic
- Blockchain Developerroleanchors this topic
- Cyber Security Expertroleanchors this topic
- Data Analystroleanchors this topic
- Data Engineerroleanchors this topic
- DevOps / SRE Engineerroleanchors this topic
- DevSecOps Engineerroleanchors this topic
- Forward Deployed Engineerroleanchors this topic
- Frontend Developerroleanchors this topic
- Full Stack Developerroleanchors this topic
- Game Developerroleanchors this topic
- Java Backend Developerroleanchors this topic
- Java SDETroleanchors this topic
- Kotlin Backend Developerroleanchors this topic
- MLOps Engineerroleanchors this topic
- Machine Learning Engineerroleanchors this topic
- Network Engineerroleanchors this topic
- PostgreSQL DBAroleanchors this topic
- QA Engineerroleanchors this topic
- Software Architectroleanchors this topic
- iOS Developerroleanchors this topic
- Computer Scienceskill
- Data Structures & Algorithmsskill
questions
833 · 16 sectionsWhat does an amortized O(1) guarantee actually promise about a single operation?
basics
~20 sAmortized O(1) promises nothing about one call, which may cost O(n). It bounds the total cost of any n operations at O(n) — a worst-case guarantee over a whole sequence, not an average over likely inputs.
Why is appending to a growth-doubling dynamic array O(1) amortized when one append copies everything?
basics
~20 sDoubling makes each resize twice as rare as the last, so the copies across n appends sum to 1+2+4+...+n, which stays under 2n. That is O(n) total work spread over n appends, hence O(1) per append on average over the sequence.
An input bound of 100,000 bookings — what time complexity should you target, and why?
basics
~20 sTarget O(n log n) or better. Quadratic work at n = 100,000 is about 10^10 operations, far past the rough budget of 10^8 simple operations per second, while n log n lands near 1.7 million — comfortably inside it.
Why do two sequential loops over n records cost O(n), but one nested inside the other O(n^2)?
basics
~20 sLoops side by side add their trip counts: n + n = 2n, and constants drop, so it stays O(n). Nesting multiplies instead: the inner loop restarts in full for every outer step, giving n * n = O(n^2).
A dynamic array's size falls from a million to twelve — why doesn't its memory footprint fall too?
basics
~20 sA dynamic array tracks two separate numbers: size, the elements in use, and capacity, the slots allocated. Removing elements lowers size only. The underlying buffer stays as large as it ever grew until something explicitly shrinks it.
Why does a growable array track both a size and a capacity, and what happens when they are equal?
basics
~20 sSize is how many elements are stored; capacity is how many slots the underlying block can hold. Appending when size equals capacity forces allocating a larger block, copying every stored element into it, and releasing the old one.
After in-place compaction with a write pointer, why must the caller be given a returned length?
basics
~10 sIn-place compaction never shrinks the array, so survivors occupy only a prefix and stale values still sit in the tail. The returned write count is the only signal of how many entries are valid.
Why does an in-place array reversal need only n/2 swaps rather than n?
basics
~10 sEach swap places two elements at once, so n/2 swaps fix all n positions. Looping over every index instead swaps each pair twice, which undoes the reversal and hands back the original array.
Why does a flat pixel buffer index as y*width+x, and what breaks if you write x*width+y?
basics
~20 sA flat row-major buffer stores each row as width consecutive slots, so the cell at column x, row y lives at ywidth+x. Writing xwidth+y addresses the transposed cell: harmless-looking on square images, corrupting or overrunning everything else.
In a linked list, why is there no address arithmetic to reach the k-th node?
basics
~20 sA linked list's nodes are separately allocated and scattered in memory, so there is no base address plus fixed stride to compute. Each node knows only where the next one lives, so reaching index k means following k links.
Why does a dummy head node remove the special case for deleting the first element?
basics
~20 sA dummy head is a permanent node placed before the first real element, so every real node has a predecessor. Deletion is always relink-the-predecessor, which means the first element needs no branch of its own.
In a singly-linked list, why is appending at the end O(n), and what makes it O(1)?
basics
~20 sAppending is O(n) when only a head reference is kept, because the last node is reachable only by walking the whole chain. Storing a tail reference alongside the head makes append O(1) in any of the three variants.
How do you detect whether a singly linked list has a cycle, and why does a plain walk hang?
basics
~20 sWalk two references, one hopping one node per step and one hopping two. If they meet, the list has a cycle; if the fast one runs off the end, it does not. A plain walk never reaches an end, so it spins forever.
Why does removing a node from a singly linked list need the predecessor, and what does that cost?
basics
~20 sA singly linked node stores only a forward link, so nothing inside it can change what points at it. Removal means rewriting the predecessor's link to skip the node, and locating that predecessor from the head costs O(n).
How does a deque give you both stack and queue behavior, and what does each of its four operations cost?
basics
~20 sA deque supports push and pop at both ends, each constant time. Pushing and popping at the same end gives LIFO stack behavior; pushing at one end and popping at the other gives FIFO queue behavior.
Array-backed vs linked-node stack: what does a single push cost in each?
basics
~20 sLinked-node push is O(1) worst case: allocate a node and link it to the head. Array-backed push is O(1) amortized: usually one slot write, but a full buffer forces copying every element into a larger block.
In a queue built from two stacks, when may elements move from the inbound to the outbound stack?
basics
~20 sOnly when the outbound stack is empty. Pushing the inbound stack's contents onto a non-empty outbound stack puts newer arrivals above older ones and destroys first-in-first-out order. Standard implementations drain the inbound stack completely in that one transfer.
Why does level-order traversal of a company org chart use a queue instead of a stack?
basics
~20 sA queue hands nodes back in the order they were discovered, so every person at one depth is expanded before anyone a depth lower. A stack returns the most recent discovery first, which dives down a single reporting chain instead.
Why is dequeuing from the front of an array-backed queue O(n), and what does that cost a backlog?
basics
~20 sRemoving the element at index 0 slides every remaining element one slot toward the front, so a single dequeue costs O(n). Draining a backlog of n items that way costs about n^2/2 moves in total.
In a bloom filter, what does a 'yes' answer guarantee and what does a 'no' answer guarantee?
basics
~20 sA bloom filter's 'no' is certain: that item was never added. Its 'yes' means only 'probably present' — a fraction of queries for items that were never added still come back positive. Negatives are facts, positives are hints.
In an O(1) LRU cache, why isn't a hash map alone enough, and what does the doubly linked list add?
basics
~20 sThe hash map gives O(1) lookup from key to node but knows nothing about recency. The doubly linked list orders nodes by last use, so the eviction victim sits at a known end and unlinking it costs O(1).
What does an ordered map give you that a hash map does not, and what do you pay for it?
basics
~20 sAn ordered map keeps its keys in sorted order, so it supports in-order iteration, range scans between two keys, and nearest-key lookups. You pay O(log n) on every insert, lookup and delete instead of a hash map's expected O(1).
In a linear-probing hash table, how does a lookup find a key that collided when it was inserted?
basics
~20 sLinear probing puts a colliding key in the next free slot, so lookup replays that walk: start at the home slot and step forward comparing keys, stopping only at an empty slot, never at the first non-matching key.
In separate chaining, what happens when two keys hash to the same bucket, and what does a lookup then cost?
basics
~20 sBoth keys stay: the bucket holds a list, and the new entry is linked into that list. A lookup indexes the bucket in constant time, then walks the chain comparing full keys, so its cost grows with the chain's length.
How does tree recursion change when a node holds a list of children instead of left and right?
basics
~10 sThe two hardcoded recursive calls become one loop over the children list, and the null-child check becomes an empty-children-list check. Every node is still visited exactly once, so a full traversal is still O(n).
In an AVL tree, what is a node's balance factor and which values are legal?
basics
~20 sA node's balance factor is its left subtree's height minus its right subtree's height. An AVL tree is valid when every node's factor is -1, 0 or +1 — a bound on heights, not on node counts.
What do a red-black tree's color invariants guarantee, and is the tree perfectly balanced?
basics
~20 sRed-black rules — no red node has a red child, and every root-to-leaf path crosses equally many black nodes — cap height near 2·log n. That is bounded, not perfectly balanced: one branch may be twice as deep as another.
In a binary tree, what is the difference between the height of a node and its depth?
basics
~20 sDepth counts edges from the root down to the node; height counts edges from the node down to its deepest descendant. Depth is fixed by where a node sits, while height depends on whatever hangs below it.
In preorder, inorder and postorder traversal of a binary tree, what actually changes between them?
basics
~20 sAll three walk the left subtree before the right; only the position of the node's own visit moves — before both subtree walks (preorder), between them (inorder), or after both (postorder). All three are depth-first and all cost O(n).
Why is extract-min from a min-heap O(log n) when the minimum already sits at the root?
basics
~20 sFinding the minimum is O(1) — it sits at the root. Removing it costs O(log n): the last element is moved into the empty root slot and sifted down through the tree's height until the heap property holds again.
Why is bottom-up heapify cheaper than inserting n items one at a time into a heap?
basics
~20 sBottom-up heapify turns an array of n items into a heap in O(n) time, while n successive inserts cost O(n log n) in the worst case. Same heap, lower cost, whenever every item is available up front.
In a min-heap held in an array, is that array sorted, and what does the heap property actually guarantee?
basics
~20 sA min-heap's array is not sorted. The property constrains only parent versus child, so every root-to-leaf path is non-decreasing while siblings may sit in any order. Only index 0 is guaranteed: it holds the minimum.
What operations define the priority queue abstraction, and how does it differ from a FIFO queue?
basics
~20 sA priority queue supports three operations: insert an item with a priority, peek at the top-priority item, and extract that item. A FIFO queue hands back items in arrival order; a priority queue hands back the most urgent one first.
A standard-library priority queue only pops the smallest key, but your scheduler must serve the highest priority first. What are your options?
basics
~10 sGive the queue a reversed comparison function, or push negated numeric keys. The reversed comparison is safer and self-documenting; negation works only for numeric keys and forces every read site to remember the flip.
Why doesn't a minimum spanning tree give the cheapest route between two given nodes?
basics
~20 sA minimum spanning tree minimizes one global sum: the total weight of the edges keeping every node connected. It promises nothing about any specific pair, so its path between two nodes can cost more than a direct link.
Why does an adjacency matrix use O(V^2) space while an adjacency list uses O(V+E)?
basics
~20 sAn adjacency matrix reserves a cell for every pair of vertices, so its size depends only on V, never on the edge count. An adjacency list stores one entry per vertex plus one per actual edge, so it grows with E.
In a warehouse robot's floor grid, what plays the role of nodes and edges in a graph?
basics
~20 sEach open cell is a node; an edge joins two cells one step apart, up, down, left or right. No edge list exists anywhere: a direction array plus a bounds-and-blocked check produces a cell's neighbors on demand.
Why does Bellman-Ford relax every edge V-1 times rather than once?
basics
~20 sAfter k passes over all edges, Bellman-Ford holds the best route that uses at most k edges. When no negative cycle exists, a best route never repeats a vertex, so it spans at most V-1 edges.
What does Dijkstra's algorithm compute on a travel-time road map, and in what order does it finalize vertices?
basics
~20 sDijkstra computes the minimum total travel time from one source to every reachable intersection - cheapest total weight, not fewest road segments. Vertices are finalized in non-decreasing distance order, so once one is popped its distance never changes.
Heapsort sorts in place — where does the heap live, and how does the array change as it runs?
basics
~20 sHeapsort builds its max-heap inside the input array itself — nothing extra is allocated. The array splits into a heap prefix and a growing sorted suffix; each round swaps the root to the boundary and shrinks the heap by one.
Why is merge sort O(n log n) on every input, including data that arrives already sorted?
basics
~20 sMerge sort always halves the input until single-element runs remain, then merges back up. That gives about log2 n levels, and every level moves all n elements once, so the total is n log n whatever the input order.
Quicksort averages O(n log n) — what input drives it to O(n^2), and why?
basics
~20 sQuicksort degrades to O(n^2) when every pivot splits off almost nothing — classically ordered input against a fixed first- or last-element pivot. Partitioning then peels one element per level, giving n levels of linear work instead of log n.
Bubble sort and selection sort are both O(n^2) — what does one pass of each accomplish?
basics
~10 sA bubble sort pass swaps out-of-order adjacent pairs, carrying the largest remaining value to the end. A selection sort pass scans the unsorted region for its minimum and places it with one swap.
Why does insertion sort run in near-linear time on nearly-ordered input but quadratic time on reversed input?
basics
~20 sInsertion sort's work is proportional to how far elements must move. Each element shifts past only the larger elements before it, so nearly-ordered input costs a few shifts per element; reversed input forces every element past every predecessor.
In a sorted array, what does a lower bound search return when the target value is absent?
basics
~20 sA lower bound search returns the first index whose element is greater than or equal to the target. For an absent key that index is exactly where the value would be inserted to keep the array sorted. It never reports failure.
Why does a plain binary search return an arbitrary index when the sorted array holds duplicate keys?
basics
~20 sA plain binary search returns the moment a midpoint matches, so which member of a run of equal keys comes back depends only on where the splits fell. The leftmost occurrence requires searching on after a hit.
Why does binary search need only about log2(n) comparisons where a linear scan needs n?
basics
~20 sEach comparison discards half of the remaining candidates, so the range shrinks n, n/2, n/4, down to one. The number of halvings needed to reach a single candidate is log2(n), so that many comparisons suffice.
Why do binary search implementations compute mid as lo + (hi - lo) / 2 instead of (lo + hi) / 2?
basics
~20 sAdding lo and hi can overflow a fixed-width signed integer once indices grow large, wrapping negative and yielding an out-of-range midpoint. Computing lo + (hi - lo) / 2 keeps every intermediate value inside the valid index range.
Why is linear search still O(n) even though it exits early on the first match?
basics
~20 sLinear search is O(n) because the bound is set by the worst case: a match in the last position, or no match at all, forces a scan of every element. Early exit improves lucky runs, not the growth rate.
Merge sort and quicksort are both divide and conquer — which phase does each spend its per-level work in?
basics
~20 sQuicksort spends in the divide step: partitioning is a linear pass, and when the halves return there is nothing to combine. Merge sort splits by index in constant time and pays its linear pass when combining.
What makes a recursive algorithm divide-and-conquer rather than plain recursion?
basics
~20 sDivide-and-conquer splits a problem into two or more subproblems of the same kind on a fraction of the input, solves them independently, and combines their answers. A function that merely calls itself does none of that by default.
Why does enumerating all subsets of n flags give 2^n results but all orderings give n!?
basics
~20 sSubsets ask one yes/no question per item: n independent binary decisions, so 2^n outcomes. Orderings fill n positions from a shrinking pool: n choices, then n-1, then n-2, down to 1, which multiplies out to n!.
In grid path backtracking, why must a cell be un-marked after its recursive branch returns?
basics
~20 sA cell is marked only to keep the path currently being built from reusing it. Once that branch returns, the cell is no longer on the path, so leaving it marked wrongly blocks every other path that needs to pass through it.
Why prune a backtracking branch as soon as the running total exceeds the budget rather than at the leaf?
basics
~20 sTesting only at the leaf still walks every branch to the bottom. Testing on entry deletes a whole subtree in one return: once the running total is over budget, more items can never bring it back down.
In a right-and-down-only grid, why is a cell's route count the sum of the cells above and left?
basics
~20 sEvery route into a cell takes its last step from either the cell above or the cell to its left. Those two sets of routes are disjoint and together cover every route, so the two counts simply add.
In 0/1 knapsack, what does dp[i][w] hold and which two candidates does the recurrence compare?
basics
~20 sdp[i][w] is the best total value reachable using only the first i items within a capacity of w. The recurrence takes the larger of leaving item i out, dp[i-1][w], and taking it, value[i] + dp[i-1][w - weight[i]], when it fits.
In minimum-coins change-making, what does dp[a] hold and how do you mark unreachable amounts?
basics
~10 sdp[a] holds the fewest coins summing exactly to amount a: one plus the smallest dp[a - c] over each denomination c that fits. Amounts no combination reaches carry an infinity sentinel, never 0.
Why does greedily picking the highest-value non-adjacent ad slots miss the optimal schedule?
basics
~20 sGreedy commits to a big slot before knowing what it blocks: taking a slot forbids both neighbours, so two merely good neighbours can outvalue one great slot. The take-or-skip recurrence best(i) = max(best(i-1), value(i) + best(i-2)) weighs both futures.
In an edit distance table over two contact names, what does dp[i][j] mean and what fills row 0?
basics
~20 sdp[i][j] is the edit distance between the first i characters of one name and the first j of the other — the indexes are prefix LENGTHS, not positions. Row 0 holds 0,1,2,...,j: turning nothing into a j-character prefix costs j insertions.
Why must a Huffman code be prefix-free, and what breaks in decoding without it?
basics
~20 sPrefix-free means no codeword is the beginning of another, so a decoder reading bits one at a time always knows exactly where a symbol ends. Without that property the same bit stream decodes several different ways.
Why does earliest-finish-time beat shortest-duration when picking the most non-overlapping talks?
basics
~20 sChoosing the talk that finishes earliest leaves the largest possible remaining window for everything after it, and that rule is provably optimal. Shortest-duration is not: one short talk can straddle the seam between two longer talks and cost you a slot.
Why does one furthest-reach counter decide whether you can cross a river of stones, each stone i allowing a leap of at most a[i] forward?
basics
~20 sReachability is monotone: standing on stone i makes every stone up to i + a[i] reachable too. So one pass keeping the maximum of i + a[i], abandoning the crossing as soon as the index passes that maximum, settles it in O(n).
In an exchange argument for a greedy algorithm, what do you swap and what must the swap show?
basics
~20 sAn exchange argument starts from any optimal solution, finds the first point where it disagrees with greedy, and swaps greedy's choice in. The swap must stay feasible and no worse, so some optimal solution agrees with greedy.
Why can nearest-stop greedy routing, taking the closest undelivered address each time, produce a poor total route?
basics
~20 sEach nearest-stop pick is cheapest right now but reshapes what remains. Cheap early hops strand far-apart addresses for the end, so a chain of locally best moves need not add up to the best route.
In cyclic sort over values 1..n, why does one final scan reveal a missing value?
basics
~20 sCyclic sort moves every value v to index v-1, so once placement finishes index i must hold i+1. The first index that breaks that rule names the absent value outright, with no extra lookup structure.
Why can't a singly linked chain be palindrome-checked by converging pointers from both ends?
basics
~20 sA singly linked chain has no backward pointers, so nothing can walk from the tail inward. The standard fix splits the chain at the middle, reverses the back half in place, then compares the two halves node by node.
Why must overlapping intervals be sorted by start before a single-pass merge?
basics
~20 sSorting by start guarantees any interval that could overlap the one being built arrives before the pass moves past it. In arrival order, an overlapping slot can appear after you already emitted an interval, so a single pass misses merges.
What single condition tells you two half-open intervals [start, end) overlap?
basics
~20 sTwo half-open intervals overlap exactly when a.start < b.end and b.start < a.end. That pair of strict comparisons is the negation of the only two ways intervals can miss each other: one finishing at or before the other begins.
How does a sweep line find the maximum number of sessions open at once in a login/logout log?
basics
~20 sA sweep line throws away the intervals and keeps only their boundaries: +1 at each login coordinate, -1 at each logout. Sort those events by coordinate, scan once with a running sum, and remember the largest sum seen.
In a permission bitmask, how do you grant, revoke and test one flag without disturbing the others?
basics
~20 sGrant with OR: mask | FLAG. Revoke by ANDing the complement: mask & ~FLAG. Test membership with (mask & FLAG) != 0. XOR toggles rather than clears, so it is the wrong operator for revoke.
Why does an 8-bit two's-complement integer range from -128 to 127 rather than -127 to 127?
basics
~20 sTwo's complement gives the top bit a weight of -128, so the 256 patterns split into 128 negatives (-128 to -1) and 128 non-negatives. Zero uses one non-negative pattern, leaving only 127 positives — so -128 has no positive counterpart.
How do you clear bit k of a status word with a mask, leaving every other bit untouched?
basics
~20 sUse n = n & ~(1 << k). The shifted mask holds a single 1 at position k; inverting it gives all ones except there, so the AND forces that bit to 0 and leaves the rest unchanged.
Why does extracting a 12-bit length field from a packed 32-bit header need both a right shift and a mask?
basics
~20 sThe shift moves the field down to bit 0 so it reads as a number; the mask clears the neighbouring fields still sitting above it. Shift alone leaves garbage on top, mask alone leaves the value scaled.
Permutations vs combinations: which counts a top-3 podium from 30 entrants?
basics
~20 sPermutations count arrangements where order matters; combinations count selections where it does not. A ranked top-3 podium from 30 entrants gives 30 x 29 x 28 = 24,360 outcomes; an unordered shortlist of three gives only 4,060.
After reading a problem's constraints, what must your plan state before you write any code?
basics
~20 sA usable plan names the constraints that actually bind (input size, memory ceiling, whether data can be re-read), the time and space class you are targeting, the concrete steps and the data you keep, and what you rejected and why.
Why state a brute-force solution aloud before optimizing in a coding interview?
basics
~20 sA stated brute force proves you understood the problem, gives the interviewer a correct baseline to score, and becomes your fallback if the clever idea collapses. Silence while hunting for the optimal answer reads as being stuck.
Why restate the problem and probe edge cases before writing any code in an interview?
basics
~20 sClarifying is the cheapest place to be wrong. A couple of minutes spent restating the task and asking about empty input, single elements, duplicates and negative values beats thirty minutes spent solving the wrong problem.
A report recomputes a day's running total from scratch on every query - how do you optimize it, and what do you pay?
basics
~20 sCompute the totals once and answer each query by lookup: q queries over n rows drop from O(q*n) to one O(n) pass plus O(1) per query. You pay extra memory, and staleness whenever the underlying rows change.
In a coding interview, how do you narrate a fork between two approaches before writing code?
basics
~20 sState each approach in a sentence or two, name the cost that separates them, say which one you would take and why, then ask the interviewer to confirm before you write a line of code.