Core Idea: Sequential access with O(1) insertion/deletion at known positions. No random access, but pointer manipulation enables elegant in-place transformations.
Pointer Manipulation: Unlike arrays, we can rewire connections without shifting elements. Master the three-pointer dance (prev, curr, next) and dummy node trick.
Why Not Array? When you need O(1) insert/delete at arbitrary positions (given a reference), or when problem naturally involves following chains of references.
Goal: Reverse a singly linked list in-place.
Why Three Pointers? When we reverse curr's pointer, we lose access to the next node. Save it first! prev tracks the new "next" for curr, next saves the original chain.
Key Insight: At each step: save next, point curr back to prev, advance prev and curr. Return prev (new head) when curr becomes nil.
Foundation Pattern:
Master this - it's used in reorder, k-group, palindrome problems.Goal: Merge two sorted lists into one sorted list.
Why Dummy Node? We don't know which list provides the head until we compare. Dummy lets us build the result without special-casing the first node.
Key Insight: Compare heads, attach smaller to result, advance that list. When one exhausts, attach the remainder of the other.
Don't Forget:
Handle nil inputs - return the other list directly.Goal: Remove the nth node from the end in one pass.
Why Two Pointers? Create a gap of n nodes between right and left. When right hits nil, left is exactly at the node before the target.
Key Insight: Use dummy node so left can point to "before head" when removing the first node. Advance right by n first, then move both until right is nil.
Gap Pattern:
Offset pointers to find relative positions without counting length.Goal: Reorder [0,1,2,3,4,5] to [0,5,1,4,2,3] - interleave front and back.
Why This Combo? We need to access from both ends. Since we can't go backward, split at middle, reverse second half, then merge alternately.
Key Insight: Three-step process: (1) Fast/slow to find middle, (2) Reverse second half, (3) Interleave first and reversed second half.
Composite Pattern:
Combines fast/slow, reversal, and merge - know each piece!Goal: Add two numbers represented as reversed linked lists (321 = 1->2->3).
Why Reversed Order Helps: Least significant digit first matches natural addition order. No need to reverse - just iterate and carry.
Key Insight: Handle unequal lengths by treating missing nodes as 0. Continue while either list has nodes OR carry is non-zero.
Don't Forget:
Final carry! [9,9] + [1] = [0,0,1], not [0,0].Goal: Deep copy a list where each node has a random pointer to any node.
Why HashMap? When copying node A, its random might point to node B that we haven't created yet. Map lets us create nodes on-demand and link later.
Key Insight: For each node, ensure it and its next/random targets exist in map. Create if not exists, then wire up the copy's pointers.
O(1) Space Alternative:
Interleave copies (A->A'->B->B'), set randoms, then separate.Goal: Implement cache with O(1) get/put, evicting least recently used on capacity overflow.
Why DLL + HashMap? HashMap gives O(1) key lookup. DLL gives O(1) removal and insertion at ends. Together: O(1) access with ordering.
Key Insight: DLL maintains usage order (head=LRU, tail=MRU). On access: remove node, add to tail. On eviction: remove from head. HashMap maps key to DLL node.
Sentinel Nodes:
Dummy head/tail simplify edge cases - never remove them!Why Key in Node?
When evicting LRU, we need its key to delete from HashMap.Goal: Merge k sorted linked lists into one sorted list.
Why Min Heap? At each step, we need the smallest among k list heads. Heap gives O(log k) for this vs O(k) linear scan. Total: O(n log k).
Key Insight: Push all k heads to heap. Pop min, add to result, push its next (if exists). Repeat until heap empty.
Pair up lists, merge each pair, repeat. Like merge sort - O(n log k) time, O(1) extra space.
Trade-off:
Heap is simpler to code; D&C uses less space.Goal: Reverse every k consecutive nodes. Leave remainder as-is if less than k.
Why Check First? Must verify k nodes exist before reversing. Otherwise, we'd reverse a partial group then struggle to undo.
Key Insight: For each group: (1) Count k nodes ahead, (2) If k exist, reverse them, (3) Connect reversed group to result. Track group boundaries carefully.
Key Detail:
Set prev = q (next group start) so reversed group connects properly.Goal: Detect if a linked list has a cycle, and find where it starts.
Visualize the list as a lollipop or letter "P": a straight stem leading to a loop.
Why They Meet: Fast gains 1 node per iteration. If cycle exists, fast will lap slow and eventually catch up inside the cycle.
When they meet:
Equating Hare's distances:
The Key Insight:
What This Means: Walking distance x from Head equals walking (k-1) full laps + z from Meeting Point. Both paths end at Cycle Start!
Visual Proof: Pointer from head walks x. Pointer from meeting point walks z (to cycle start) then possibly more full laps. They converge at cycle start.
Application:
Find Duplicate Number - treat array as linked list where arr[i] points to arr[arr[i]].Goal: Return true if cycle exists in linked list.
Why It Works: If there's a cycle, fast pointer enters it first. Slow follows. Fast gains 1 node per step, so it will eventually catch slow inside the cycle.
Check Both:
fast != nil AND fast.Next != nil (fast moves 2 steps).Goal: In array of n+1 integers in range [1,n], find the duplicate without modifying array.
Why This Works: Treat index as "node" and arr[index] as "next pointer". Since values are in [1,n] and we have n+1 elements, there must be a cycle - the duplicate value is where multiple indices point.
Key Insight: The duplicate is the entrance to the cycle (multiple paths lead into it). Use Floyd's to find meeting point, then find cycle start.
Array as Graph:
i -> nums[i] creates edges. Duplicate = node with in-degree > 1.Use When: Head might change (merging, removing first node, inserting at front).
Template: dummy := &ListNode{Next: head} ... return dummy.Next
Examples: Merge Two Lists, Remove Nth, Add Two Numbers.
Use When: Finding middle, detecting cycles, nth from end.
Template: slow moves 1, fast moves 2. When fast ends, slow is at middle.
Examples: Reorder List (middle), Cycle Detection, Find Duplicate.
Use When: Reversing all or part of list.
Template: Three pointers - prev, curr, next. Save next, reverse curr, advance all.
Examples: Reverse LL, Reorder List, Reverse K-Group.
Use When: Finding nth from end in one pass.
Template: Advance right by n, then move both until right is nil.
Examples: Remove Nth From End.
Use When: Need O(1) lookup AND ordering/sequential access.
Template: HashMap for key->node, DLL for order. Update both on access.
Examples: LRU Cache, Copy Random List.
Use When: Combining sorted lists.
Template: Compare heads, attach smaller, advance. Handle remainders.
Examples: Merge Two Lists, Merge K Lists.
Common Thread:
Linked lists excel at O(1) insert/delete with known position. Use pointers creatively - multiple pointers at different speeds, gaps, or reversals unlock elegant O(1) space solutions.