FAANG Interview Prep
Foundations, Memory & Complexity
Big-O notation, time/space analysis, memory layoutRecursion Complete Guide
Base cases, call stack, tail recursion, memoizationArrays & Array ADT
Static/dynamic arrays, operations, amortized analysisStrings
Pattern matching, string algorithms, encoding, manipulationMatrices
2D arrays, sparse matrices, matrix operations, traversalsLinked Lists
Singly, doubly, circular lists, pointer manipulationStack
LIFO, push/pop, expression evaluation, backtrackingQueue
FIFO, circular queue, deque, priority queueTrees
Binary trees, traversals, expression trees, threaded treesBST & Balanced Trees
Search, insert, delete, AVL, red-black, B-treesHeaps, Sorting & Hashing
Min/max heaps, heapsort, hash tables, collision handlingGraphs, DP, Greedy & Backtracking
BFS, DFS, shortest paths, dynamic programming, optimizationIntroduction to Linked Lists
A linked list is a linear data structure where elements are stored in nodes, and each node points to the next node in the sequence. Unlike arrays, linked lists don't require contiguous memory allocation, making insertions and deletions more efficient.
Arrays vs Linked Lists
Comparison Table
| Operation | Array | Linked List |
|---|---|---|
| Access by Index | \(O(1)\) | \(O(n)\) |
| Insert at Beginning | \(O(n)\) | \(O(1)\) |
| Insert at End | \(O(1)\)* | \(O(n)\) / \(O(1)\)** |
| Insert in Middle | \(O(n)\) | \(O(n)\)*** |
| Delete at Beginning | \(O(n)\) | \(O(1)\) |
| Search | \(O(n)\) / \(O(\log n)\)**** | \(O(n)\) |
| Memory | Contiguous | Scattered + Overhead |
* Amortized \(O(1)\) for dynamic arrays
** \(O(1)\) with tail pointer
*** \(O(1)\) once position is found
**** \(O(\log n)\) if sorted (binary search)
Singly Linked List
In a singly linked list, each node contains data and a pointer to the next node. The last node points to null (or None in Python).
Singly Linked List with Tail Pointer
The basic singly linked list has a major performance issue: appending to the end requires \(O(n)\) traversal to find the last node. Adding a tail pointer that always references the last node makes append() an \(O(1)\) operation — critical for queue implementations and any workflow that builds lists by appending. The tradeoff: you must carefully maintain the tail pointer through insertions, deletions, and edge cases (empty list, single element).
Doubly Linked List
In a doubly linked list, each node has pointers to both the next and previous nodes, enabling bidirectional traversal and \(O(1)\) deletion when you have a reference to the node.
Circular Linked List
In a circular linked list, the last node points back to the first node, creating a loop. This is useful for applications like round-robin scheduling, circular buffers, and playlists.
Circular Doubly Linked List
Key Techniques
List Reversal
Reversing a linked list is the single most common interview question on linked lists. The iterative three-pointer technique uses prev, current, and next: at each step, save current.next, reverse the link (current.next = prev), then advance all three pointers. After one pass, the list is reversed in \(O(n)\) time with \(O(1)\) space. The recursive approach is elegant but uses \(O(n)\) stack space.
Variations to master: Reverse between positions \(m\) and \(n\) (LeetCode 92), reverse in K-groups (LeetCode 25), and check if a list is a palindrome (reverse second half, then compare).
Two Pointer Techniques
The slow/fast pointer (Floyd's Tortoise and Hare) pattern is the Swiss Army knife of linked list problems. One pointer moves 1 step at a time, the other moves 2 steps. When fast reaches the end, slow is at the middle. This technique also detects cycles (if fast catches slow, there's a cycle) and finds the start of a cycle. Other two-pointer patterns: maintain a gap of K nodes between pointers to find the K-th node from the end in one pass.
Cycle Detection
Floyd's Cycle Detection proves mathematically that if a cycle exists, the fast pointer (2 steps) will eventually meet the slow pointer (1 step) inside the cycle. To find where the cycle starts: once they meet, reset one pointer to head and advance both at speed 1 — they'll meet exactly at the cycle's entry point. This is because the distance from head to cycle start equals the distance from the meeting point to cycle start (modulo cycle length).
Real-World Applications of Cycle Detection
Memory leak detection (circular references in garbage collectors), infinite loop detection in state machines, finding duplicates in arrays (LeetCode 287 — treat array values as "next" pointers), and deadlock detection in operating systems (resource allocation graphs with cycles).
LeetCode Practice Problems
Easy 206. Reverse Linked List
Reverse a singly linked list.
Easy 21. Merge Two Sorted Lists
Merge two sorted linked lists into one sorted list.
Easy 141. Linked List Cycle
Determine if a linked list has a cycle.
Medium 19. Remove Nth Node From End
Remove the nth node from the end in one pass.
Medium 142. Linked List Cycle II
Find the node where the cycle begins.
Medium 148. Sort List
Sort a linked list in \(O(n \log n)\) time using constant space.
Hard 25. Reverse Nodes in k-Group
Reverse nodes in groups of k. If remaining < k, leave as-is.
Next in the Series
In Part 7: Stack, we’ll use linked-list nodes to build stacks — the LIFO structure behind expression evaluation, parenthesis matching, and backtracking algorithms.