The Data Structures Cheatsheet: Time & Space Complexity for Every Structure You Need#

Bookmark this page. Whether you’re cramming the night before a FAANG interview or just need to double-check whether deleting from a heap is O(log n) or O(n), this cheatsheet covers the ten data structures that account for nearly every coding interview question: arrays, linked lists, stacks, queues, hash maps, sets, trees, heaps, graphs, and tries.

For each structure you’ll find the time complexity of the core operations (average and worst case), space complexity, a minimal Python snippet, and the situations where it’s the right tool. Every section links to the full lesson in our 60-day curriculum if you want to go deeper.


The Master Table#

If you only have five minutes, this is the table to scan. Complexities are average case; worst cases follow in the per-structure sections.

StructureAccessSearchInsertDeleteSpace
Array (dynamic)O(1)O(n)O(n)*O(n)O(n)
Linked ListO(n)O(n)O(1)**O(1)**O(n)
StackO(n)O(n)O(1)O(1)O(n)
QueueO(n)O(n)O(1)O(1)O(n)
Hash MapN/AO(1)O(1)O(1)O(n)
SetN/AO(1)O(1)O(1)O(n)
Binary Search TreeO(log n)O(log n)O(log n)O(log n)O(n)
HeapO(1) peekO(n)O(log n)O(log n)O(n)
Graph (adjacency list)N/AO(V + E)O(1)O(E)O(V + E)
TrieN/AO(m)O(m)O(m)O(alphabet × m × n)

* O(1) amortized when appending to the end.  ** O(1) once you hold a reference to the node; finding it costs O(n).

Where n is the number of elements, V/E are vertices/edges, and m is key length (for tries).


1. Arrays#

Contiguous memory, index-based access. Python’s list is a dynamic array.

OperationAverageWorst
Access by indexO(1)O(1)
Search (unsorted)O(n)O(n)
Search (sorted, binary search)O(log n)O(log n)
Append at endO(1) amortizedO(n) (resize)
Insert/delete at front or middleO(n)O(n)

Space: O(n)

1nums = [3, 1, 4, 1, 5]
2nums.append(9)        # O(1) amortized
3nums.insert(0, 2)     # O(n) — shifts every element
4first = nums[0]       # O(1)
5nums.sort()           # O(n log n)

Best for: index-based lookups, iteration, two-pointer and sliding-window patterns, anything where data fits in order and you rarely insert in the middle.

Study more: Day 4: Introduction to Arrays and Day 25: Binary Search.


2. Linked Lists#

Nodes connected by pointers. No random access, but O(1) insertion and deletion when you already hold a reference to the node.

OperationAverageWorst
Access by positionO(n)O(n)
SearchO(n)O(n)
Insert at headO(1)O(1)
Insert/delete at known nodeO(1)O(1)
Delete by valueO(n)O(n)

Space: O(n), plus pointer overhead per node

 1class Node:
 2    def __init__(self, val):
 3        self.val = val
 4        self.next = None
 5
 6head = Node(1)
 7head.next = Node(2)          # insert after head: O(1)
 8new = Node(0)
 9new.next = head              # insert at head: O(1)
10head = new

Best for: frequent insertion/deletion at the ends, implementing stacks/queues/LRU caches, problems built around pointer manipulation (reverse a list, detect a cycle, merge sorted lists).

Study more: Day 7: Introduction to Linked Lists, Day 9: Doubly Linked Lists, and Day 10: Advanced Linked List Operations.


3. Stacks#

LIFO: last in, first out. In Python, just use a list with append/pop.

OperationAverageWorst
PushO(1)O(1)
PopO(1)O(1)
PeekO(1)O(1)
SearchO(n)O(n)

Space: O(n)

1stack = []
2stack.append("a")   # push
3stack.append("b")
4top = stack[-1]     # peek -> "b"
5stack.pop()         # pop  -> "b"

Best for: matching brackets, undo history, expression evaluation, iterative DFS, monotonic-stack problems (next greater element, largest rectangle in histogram).

Study more: Day 11: Stacks.


4. Queues#

FIFO: first in, first out. Use collections.deque, never a plain list (popping from the front of a list is O(n)).

OperationAverageWorst
EnqueueO(1)O(1)
DequeueO(1)O(1)
PeekO(1)O(1)
SearchO(n)O(n)

Space: O(n)

1from collections import deque
2
3q = deque()
4q.append("first")     # enqueue
5q.append("second")
6front = q[0]          # peek -> "first"
7q.popleft()           # dequeue -> "first"

Best for: BFS on trees and graphs, level-order traversal, sliding-window maximum (as a monotonic deque), task scheduling and producer/consumer patterns.

Study more: Day 12: Queues and Day 20: Graph Traversals.


5. Hash Maps (Dictionaries)#

Key → value mapping backed by a hash table. Python’s dict. The single most useful structure in interviews.

OperationAverageWorst
LookupO(1)O(n)
InsertO(1)O(n)
DeleteO(1)O(n)

The O(n) worst case happens only under pathological collisions or during a resize. Treat hash map operations as O(1) in interviews, but say you know the worst case exists. Interviewers listen for that.

Space: O(n)

1counts = {}
2for ch in "interview":
3    counts[ch] = counts.get(ch, 0) + 1
4
5# Or, idiomatically:
6from collections import Counter, defaultdict
7counts = Counter("interview")
8graph = defaultdict(list)   # great for adjacency lists

Best for: frequency counting, memoization, two-sum-style complement lookups, grouping (anagrams), caching, de-duplication with metadata.

Study more: Day 23: Hash Tables.


6. Sets#

A hash map without values. Membership tests in O(1) average.

OperationAverageWorst
Membership (x in s)O(1)O(n)
AddO(1)O(n)
RemoveO(1)O(n)
Union / IntersectionO(len(a) + len(b))N/A

Space: O(n)

1seen = set()
2seen.add(42)
3if 42 in seen:              # O(1) average
4    print("duplicate!")
5
6evens = {2, 4, 6}
7primes = {2, 3, 5}
8print(evens & primes)       # intersection -> {2}
9print(evens | primes)       # union -> {2, 3, 4, 5, 6}

Best for: duplicate detection, “have I visited this node?” checks in graph traversal, longest consecutive sequence, set-algebra problems.

Study more: Day 24: Sets.


7. Trees (Binary Search Trees)#

Hierarchical nodes; a BST keeps left < node < right, giving logarithmic operations when balanced.

OperationAverage (balanced)Worst (degenerate)
SearchO(log n)O(n)
InsertO(log n)O(n)
DeleteO(log n)O(n)
TraversalO(n)O(n)

Space: O(n); recursion stack adds O(h) where h is the height.

 1class TreeNode:
 2    def __init__(self, val):
 3        self.val = val
 4        self.left = None
 5        self.right = None
 6
 7def insert(root, val):
 8    if root is None:
 9        return TreeNode(val)
10    if val < root.val:
11        root.left = insert(root.left, val)
12    else:
13        root.right = insert(root.right, val)
14    return root

A BST built from sorted input degenerates into a linked list. That’s the O(n) worst case. Self-balancing variants (AVL, Red-Black) guarantee O(log n).

Best for: sorted data with dynamic inserts, range queries, in-order traversal producing sorted output, and the enormous family of tree-recursion interview questions.

Study more: Day 13: Trees Introduction, Day 15: Binary Search Trees, and Day 16: Tree Traversals.


8. Heaps (Priority Queues)#

A complete binary tree stored in an array, where every parent beats its children (min-heap: parent ≤ children). Python’s heapq is a min-heap.

OperationAverageWorst
Peek min/maxO(1)O(1)
Insert (push)O(log n)O(log n)
Extract min/max (pop)O(log n)O(log n)
Build heap from arrayO(n)O(n)
Search arbitrary elementO(n)O(n)

Space: O(n)

 1import heapq
 2
 3nums = [5, 1, 8, 3]
 4heapq.heapify(nums)          # O(n)
 5heapq.heappush(nums, 2)      # O(log n)
 6smallest = heapq.heappop(nums)   # O(log n) -> 1
 7
 8# Max-heap trick: negate values
 9heapq.heappush(max_heap := [], -5)
10largest = -heapq.heappop(max_heap)

Best for: top-K problems, merging K sorted lists, running median (two heaps), Dijkstra’s algorithm, any “repeatedly grab the smallest/largest” pattern.

Study more: Day 17: Heaps and Day 28: Heapsort.


9. Graphs#

Vertices connected by edges. In interviews, the adjacency list (a dict of lists) wins almost every time.

OperationAdjacency ListAdjacency Matrix
Add vertexO(1)O(V²)
Add edgeO(1)O(1)
Check edge (u, v)O(degree(u))O(1)
Iterate neighborsO(degree(u))O(V)
SpaceO(V + E)O(V²)

BFS and DFS both run in O(V + E) with O(V) extra space.

 1from collections import defaultdict, deque
 2
 3graph = defaultdict(list)
 4for u, v in [(0, 1), (0, 2), (1, 3)]:
 5    graph[u].append(v)
 6    graph[v].append(u)      # omit for directed graphs
 7
 8def bfs(start):
 9    visited, q = {start}, deque([start])
10    while q:
11        node = q.popleft()
12        for nxt in graph[node]:
13            if nxt not in visited:
14                visited.add(nxt)
15                q.append(nxt)

Best for: anything with relationships, such as islands in a grid, course scheduling (topological sort), shortest paths, connected components, cycle detection.

Study more: Day 18: Graphs Introduction, Day 19: Graph Representations, and Day 21: Shortest Path Algorithms.


10. Tries (Prefix Trees)#

A tree keyed by characters, where each root-to-node path spells a prefix. Complexity depends on key length m, not the number of stored words.

OperationComplexity
Insert wordO(m)
Search wordO(m)
Search prefixO(m)
SpaceO(alphabet × m × n) worst case
 1class TrieNode:
 2    def __init__(self):
 3        self.children = {}
 4        self.is_word = False
 5
 6class Trie:
 7    def __init__(self):
 8        self.root = TrieNode()
 9
10    def insert(self, word):
11        node = self.root
12        for ch in word:
13            node = node.children.setdefault(ch, TrieNode())
14        node.is_word = True
15
16    def starts_with(self, prefix):
17        node = self.root
18        for ch in prefix:
19            if ch not in node.children:
20                return False
21            node = node.children[ch]
22        return True

Best for: autocomplete, spell-checking, prefix matching, word-search puzzles on grids. If a problem says “prefix”, think trie first. We cover tries in depth in Tries Explained Simply.

Study more: Day 58: Tries.


How to Actually Memorize This#

Don’t. Memorizing tables is fragile under interview pressure. Instead, internalize three rules that regenerate most of the table on demand:

  1. Contiguous memory gives O(1) access but O(n) middle insertion: that’s arrays.
  2. Pointers give O(1) insertion but O(n) access: linked structures.
  3. Hashing trades order for O(1) average everything: maps and sets.

Trees and heaps are “logarithmic middle ground,” graphs are “cost proportional to what you touch (V + E),” and tries are “cost proportional to key length.”

The rest is practice. Our 60-day challenge dedicates a full day to each of these structures with implementations and exercises. Days 4–24 cover every structure in this cheatsheet in order. Sign up free and work through them one day at a time.



Happy coding, and good luck in that interview!