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

Unit 1 · Algorithms · Lesson 1 of 24

Complexity analysis

Complexity analysis predicts whether a solution fits the input limits and lets you compare designs before writing code. Interviewers expect correct time and auxiliary-space bounds in terms of every input dimension, and a clear statement of whether a bound is worst-case, expected or amortized.
About 3 hFocus mode

Step 1: Learn the ideas

  • Asymptotic notation: O, Theta, Omega and tight bounds
  • Word-RAM cost model and where it breaks (big integers, long keys, caches)
  • Worst-case, expected (randomized) and average-case bounds
  • Amortized analysis: aggregate, accounting and potential methods
  • Auxiliary space versus input and output space
  • Recursion depth as space
  • Multiple input dimensions: O(n·m), O(V + E), O(N log k)
  • Output-sensitive bounds for enumeration problems
  • Recurrences: recursion trees and the master theorem
  • Using input limits to pick a target complexity

Why it matters

Before writing code in an interview you should already know roughly how fast it will run and whether that is fast enough for the input limits. Complexity analysis gives you that prediction, lets you compare two designs without implementing both, and is the first thing an interviewer checks when you propose an approach. The same reasoning tells you in production whether a job survives ten times more data, or whether a "constant-time" lookup hides a linear scan.

Core ideas

Notation. O is an upper bound, Ω a lower bound, Θ both. In interviews "O" is usually read as a tight bound, so do not say O(n log n) if your code is O(n). Constants and lower-order terms are dropped, but they still decide between two solutions of the same class.

Which case you are stating.

  • Worst case holds for every input of size n: binary search, merge sort, heap operations.
  • Expected averages over the algorithm's own random choices, for every input: randomized quickselect, hashing with a randomly chosen hash function. It is not the same as average case, which averages over an assumed input distribution.
  • Amortized bounds the total cost of any sequence of m operations, divided by m. A dynamic array that doubles its capacity copies 1 + 2 + 4 + ... < 2n elements over n appends, so append is amortized O(1), although the single append that triggers growth costs O(n). Amortized bounds are worst-case statements about sequences; no probability is involved.

Time versus space. Report auxiliary space (what you allocate beyond the input) and say whether the output counts. Recursion consumes stack: DFS on a path-shaped tree with n nodes is n frames deep even if it allocates nothing else, while merge sort recurses only O(log n) deep.

Several input dimensions. Do not collapse independent sizes into one n. A grid search is O(rows × cols); BFS over an adjacency list is O(V + E); merging k sorted lists of N total elements with a heap is O(N log k); comparing all pairs of n words of length up to L is O(n² × L). Hashing a string key costs O(L), not O(1).

Output-sensitive bounds. When the answer is large, the bound must include it. There are 2ⁿ subsets with average size n/2, so listing them is Θ(n × 2ⁿ) for any algorithm: no method can be faster than writing its output.

Recurrences. Draw the recursion tree and sum work per level. T(n) = 2T(n/2) + O(n) has log n levels of O(n) work: O(n log n). T(n) = T(n/2) + O(1) is O(log n). T(n) = T(n − 1) + O(n) sums to O(n²), which is why a recursion that passes a copied slice a[1:] is quadratic.

From limits to a target. A rough rule of thumb is around 10⁸ simple operations per second in compiled languages and roughly an order of magnitude fewer in CPython. So n near 10⁵ to 10⁶ calls for O(n log n) or better, n near 10³ to 10⁴ allows O(n²), and n up to about 20 allows O(2ⁿ × n). Use this as a sanity check, not a law.

Common misconceptions

  • "Hash map operations are O(1)." They are expected O(1) under good hashing and a bounded load factor, plus the cost of hashing the key. Adversarial or degenerate keys make them O(n), and a resize makes an individual insert expensive.
  • "Amortized means average over random inputs." It is a guarantee for every sequence of operations; individual operations may still be slow, which matters for latency-sensitive code.
  • "Recursion costs no space." Every active call holds a frame. Depth-n recursion is O(n) space and can exceed a language's stack limit.
  • "Two nested loops mean O(n²)." Count total iterations instead. A sliding window whose left index only moves forward is O(n) despite its inner loop.
  • "Slicing and string concatenation are free." In most languages a slice copies its elements, and repeatedly concatenating immutable strings can be quadratic.
  • "The asymptotically better algorithm is always faster." Asymptotics describe growth. At realistic sizes, constants, allocation and cache behavior can reverse the ranking, which is why measurement still matters.

How to approach it

State the complexity unprompted, once when you propose an approach and again after coding, defining every variable ("n words of maximum length L"). Name the case: worst, expected or amortized. Include auxiliary space and recursion depth, and price every library call you use (sorting, slicing, membership tests on lists). At every level interviewers check the bound of your own code; at mid and senior levels they also ask how it changes when an assumption changes: keys become long strings, inputs become adversarial, or data no longer fits in memory.

Suggested order

  1. 1Read MIT 6.006 Recitation 1 (with Lecture 1: Introduction) for asymptotic notation and the model of computation, then do its asymptotics exercises.
  2. 2Read the amortized-analysis part of MIT 6.006 Lecture 2 (Data Structures) and reproduce the doubling argument for dynamic arrays on paper.
  3. 3Read the recurrences section of MIT 6.006 Recitation 3 and solve T(n) = 2T(n/2) + n, T(n) = T(n/2) + 1 and T(n) = T(n − 1) + n with recursion trees.
  4. 4For deep-level preparation, read Jeff Erickson’s lecture notes on amortized analysis (binary counter) to see the accounting and potential methods once.
  5. 5Open the official cost table for your interview language (for Python, the documentation page on time complexity of built-in types) and annotate ten operations you use daily.
  6. 6Solve Implement Queue using Stacks and explain its amortized bound, then Design HashMap and state exactly what its O(1) assumes.
  7. 7For Kth Largest Element in an Array, Merge k Sorted Lists, Subsets and Number of Islands, write the full bound with every dimension before coding.

Step 2: Check off what you can do

Tap each one you can genuinely do or explain. Each earns 10 XP.

Step 3: Go deeper

  • MIT 6.006 Introduction to Algorithms (Spring 2020)Start here

    MIT OpenCourseWare

    Section: Recitation 1

    Asymptotic notation, the word-RAM model of computation and short exercises on comparing growth rates; read with Lecture 1.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • MIT 6.006 Introduction to Algorithms (Spring 2020)

    MIT OpenCourseWare

    Section: Lecture 2: Data Structures

    The amortized analysis of dynamic arrays: why append is constant time over any sequence of operations.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • MIT 6.006 Introduction to Algorithms (Spring 2020)

    MIT OpenCourseWare

    Section: Recitation 3

    Solving recurrences with substitution, recursion trees and the master theorem, with exercises.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Algorithms (Jeff Erickson): Recursion and Backtracking chapters, with amortized-analysis notes

    Jeff Erickson, University of Illinois Urbana-Champaign

    Section: Lecture notes: Amortized Analysis

    Aggregate, accounting and potential-method arguments worked through on a binary counter, for deep-level understanding.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Python documentation: costs of built-in types and the container modules

    Python Software Foundation (docs.python.org)

    Section: Time complexity of operations on built-in types

    A concrete official cost table that shows amortized, average-case and worst-case caveats for real library operations.

    Open(opens in a new tab)Link responded, 5 Oct 2026

Step 4: Practice

Treat these as complexity exercises as much as coding exercises. Before coding, write the time and auxiliary-space bound with every input dimension and say whether it is worst-case, expected or amortized; after coding, check the bound against the code you actually wrote, including library calls and recursion depth. Contains Duplicate and Two Sum contrast sorting with hashing, Implement Queue using Stacks is the amortized example, Kth Largest contrasts expected and worst-case time, and Merge k Sorted Lists, Subsets and Number of Islands need multi-dimensional or output-sensitive bounds. Afterwards, keep the habit by stating the full bound before solving any problem from the Top Interview 150 plan.

Record attempts on each problem’s page (+15 XP, +10 more when solved on your own).

Step 5: Test yourself

Answer each one out loud or on paper before you finish the lesson.

  1. Question 1What is the difference between expected O(1) and amortized O(1)?
  2. Question 2What is the space complexity of recursive DFS on a path-shaped tree with n nodes?
  3. Question 3Why is listing all subsets of n items at least n · 2^n work for any algorithm?
  4. Question 4What does average O(1) hash lookup assume, and what does hashing a string of length L cost?
  5. Question 5Why is a recursion that passes a[1:] at each call quadratic?
  6. Question 6With n up to 2 · 10^5, which complexity classes are realistic targets?

You’re done when you can

  • State correct time and auxiliary-space bounds, including recursion depth, for five unseen solutions in about a minute each.
  • Explain without notes why dynamic-array append is amortized O(1) and why a single append can be O(n).
  • Solve three standard recurrences with recursion trees and name an algorithm that matches each.
  • Give one example each of a worst-case, an expected and an amortized guarantee, and say what assumption each depends on.

Finish the lesson

How confident do you feel?

Lesson complete!

+50 XP

Reviews will come up on the Practice tab so it sticks.

Unlocks next: Arrays, strings and hashing, Linked lists, Stacks, queues and deques, Heaps, selection and streaming, Recursion and backtracking, Bit manipulation

Your notes and study time

Log study time