Home/Learn/Linked List

Pattern Guide

Linked List

"Dummy node. Slow/fast pointers. Reverse in-place."

Linked list problems have 4-5 core techniques that combine to solve almost everything: dummy node for head modification, slow/fast pointers for middle/cycle, in-place reversal, partition+merge, and the LRU pattern.

Problems you can solve with this pattern

9 problems · click any to start solving

All linked list
1Reverse Linked List II (Reverse sublist from left to right)MediumSolve
2Reorder ListMediumSolve
3Linked List Cycle II (Find cycle entry point)MediumSolve
4LRU CacheMediumSolve
In-place reversal (prev always starts null)
// prev = null because the last node of reversed list points to nothing
let prev = null, curr = head;
while (curr) {
    const next = curr.next;  // save next before overwriting
    curr.next = prev;        // reverse the pointer
    prev = curr;             // prev advances to current
    curr = next;             // curr advances to saved next
}
return prev;  // prev is the new head
While loop condition rule: Look at what you access INSIDE the loop.
- Access curr.next → condition: while (curr)
- Access curr.next.next → condition: while (curr && curr.next)

This prevents null pointer errors without special-casing every edge condition.
Dummy node: Whenever the head node might be modified or removed, create a dummy node that points to head. This turns "delete head" into a normal node deletion — no special cases. Return dummy.next at the end.

Core Templates

In-place reversal (prev always starts null)
// prev = null because the last node of reversed list points to nothing
let prev = null, curr = head;
while (curr) {
    const next = curr.next;  // save next before overwriting
    curr.next = prev;        // reverse the pointer
    prev = curr;             // prev advances to current
    curr = next;             // curr advances to saved next
}
return prev;  // prev is the new head
Slow/fast pointer — find middle
let slow = head, fast = head;
while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
}
// slow = middle node
// for even-length: slow = second of the two middles
Partition into two lists, merge at end
let left = new ListNode(), right = new ListNode();
const lHead = left, rHead = right;

let curr = head;
while (curr) {
    if (condition(curr.val)) { left.next = curr; left = left.next; }
    else { right.next = curr; right = right.next; }
    curr = curr.next;
}
right.next = null;     // CRITICAL: null-terminate right to prevent cycle
left.next = rHead.next;
return lHead.next;
Recursive linked list reversal: works by reversing the rest of the list first, then fixing the current node's pointers when recursion unwinds.
``
if (!head || !head.next) return head;
const newHead = reverse(head.next);
head.next.next = head; // last node of reversed part now points back
head.next = null; // break old forward link
return newHead;
``

Linked list pattern checklist:
- "Find middle" → slow/fast pointers (slow ends at middle)
- "Detect cycle" → Floyd's: slow+fast, if they meet, cycle exists
- "k-th from end" → two pointers gap k apart
- "Merge/sort" → divide and conquer (merge sort on lists)
- "Copy with extra pointers" → HashMap OR interleave trick (O(1) space)