Linked List Pattern
No indexes. No jumping. Follow the chain and rewire it carefully.
Quick Summary
Best used when
- ✓You're working with nodes connected by next pointers
- ✓You need to merge, reverse, or rearrange the list in place
- ✓You need O(1) extra space — no copying to an array
- ✓You need to detect cycles or find the middle node
Clue words in the problem
Complexity gain
Array-copy approaches → O(1) space with in-place pointer manipulation
Why this pattern matters for LeetCode
Linked list problems can not use indexes. You must traverse from head and rewire next pointers in place. The most common bug is overwriting a pointer before saving it — this loses the rest of the list with no way to recover. Dummy head nodes eliminate most edge cases involving the head of the list. Once you understand pointer rewiring and the dummy head pattern, most linked list problems follow the same structure.
What the Linked List pattern is
Linked list problems require tracking and manipulating node pointers directly. Unlike arrays, you can't jump to a position by index — you traverse from head. The key techniques are: dummy head nodes (to simplify edge cases at the head), two-pointer traversal (for cycle detection and finding the k-th node from the end), and careful pointer reassignment order (for reversal and merging without losing the chain).
Reach for Linked List when you catch yourself thinking…
These are the internal questions that signal this pattern.
Beginner mental model
A linked list is like a treasure hunt where each clue tells you where the next clue is — but you can't skip ahead. You must follow the chain one step at a time. Solving linked list problems is about rewiring those clues carefully without losing the chain. The most common bug: you overwrite node.next before saving a reference to what it pointed to, and the rest of the list disappears.
Ready to practice Linked List?
DSA Trainer gives you guided hints, not answers, so you build real intuition.
When to use Linked List
- ✓Merging two sorted linked lists (classic dummy head + compare)
- ✓Reversing a linked list in place (rewire three pointers per step)
- ✓Detecting a cycle using fast and slow pointers
- ✓Finding the middle node — slow pointer lands in the middle when fast reaches the end
- ✓Removing the nth node from the end — offset two pointers by n steps
When NOT to use Linked List
- ✕The problem would be simpler if you convert to an array first (when O(n) space is acceptable)
- ✕You need random access by index — arrays are O(1), linked lists are O(n)
- ✕The problem is naturally a graph problem — linked lists only have next pointers
- ✕The input is an array — don't invent a linked list structure unnecessarily
Better alternative: In those cases, converting to an array for simplicity or using graph traversal algorithms may be more appropriate.
JavaScript code template
Merge Two Sorted Lists — O(n + m) time, O(1) space
function mergeTwoLists(
l1: ListNode | null,
l2: ListNode | null
): ListNode | null {
const dummy = new ListNode(0); // dummy head eliminates edge cases
let current = dummy;
while (l1 !== null && l2 !== null) {
if (l1.val <= l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
// Attach the remaining list (one of them is already null)
current.next = l1 ?? l2;
return dummy.next; // return actual head, skip dummy
}The dummy head node gives current.next a valid starting place — no special-casing for the first node. At each step, attach the smaller node to current.next, advance that list's pointer, then advance current. When one list runs out, attach the entire remaining portion of the other. Return dummy.next, which is the real head of the merged list.
Step-by-step thinking process
Walk through this in your head before writing code.
- 1Create a dummy head node — this simplifies insertion at the beginning and avoids null checks on the first node.
- 2Set current = dummy. This pointer will build the result list.
- 3While both l1 and l2 are non-null: compare their values, attach the smaller one to current.next, advance that list's head pointer, then advance current.
- 4When one list runs out, attach the remainder of the other list to current.next (it's already sorted).
- 5Return dummy.next — the dummy was just a placeholder; the real head starts at dummy.next.
LeetCode-style problems that use this pattern
Practice on DSA Trainer with guided hints: no spoilers, just nudges.
- Merge Two Sorted Lists
Use a dummy head and compare l1 and l2 values at each step, advancing the smaller pointer.
Premium→ - Reverse Linked List
Rewire three pointers at each step — prev, curr, and the saved next — to reverse direction.
Premium→ - Linked List Cycle
Fast and slow pointers — if they ever point to the same node, there's a cycle.
Premium→ - Middle of the Linked List
Fast moves two steps, slow moves one — when fast reaches the end, slow is at the middle.
Premium→
Coming soon
- Remove Nth Node From End of ListComing soon
Offset two pointers by n steps so the first reaches the end exactly when the second is at the target.
Common mistakes beginners make
- ✕Losing the rest of the list — always save node.next to a temp variable before overwriting node.next in reversal problems.
- ✕Accessing .val or .next without a null check — one null dereference crashes the function. Always check node !== null first.
- ✕Not using a dummy head — without it, you need special-case logic every time you insert at the beginning of the result list.
- ✕Confusing 'advance the pointer' (current = current.next) with 'change where the pointer points' (current.next = something) — they do completely different things.
Linked List pointers vs Array indexes
Choose the right tool for the job.
| Pattern | Use when… |
|---|---|
| Linked List | In-place insertion/deletion in O(1) once you have the pointer — but traversal is O(n) with no random access |
| Array | O(1) random access by index — but insertion/deletion requires shifting elements |
Time and space complexity
Time complexity
O(n) for traversal; O(n + m) for merge
Space complexity
O(1) for in-place pointer manipulation
You visit each node at most once — O(n) or O(n + m) for operations involving two lists. Pointer manipulation uses only a constant number of extra variables (dummy, current, temp), so space is O(1). The one exception: if you use recursion, the call stack is O(n) deep.
Ready to practice Linked List?
DSA Trainer gives you guided hints, not answers, so you build real intuition.
Frequently asked questions
- Why can't I use indexes with a linked list?
- Linked list nodes don't have a direct way to jump to position k. To get to node 5, you must start at head and follow next five times. This is O(k) per access, not O(1) like arrays. That's why linked list solutions use pointer manipulation instead of index arithmetic.
- What does the dummy head node actually do?
- It gives you a non-null starting point for current.next so you don't need to special-case inserting the very first node. Without it, you'd write: 'if head is null, set head to the new node; otherwise, set current.next to the new node.' The dummy absorbs that first case so your loop is uniform throughout.
- How do fast and slow pointers work for cycle detection?
- Slow moves one node at a time; fast moves two. If there's no cycle, fast reaches null. If there's a cycle, fast laps slow inside the cycle and they meet at the same node. This is Floyd's cycle detection algorithm — O(n) time, O(1) space.
- What's the most common null pointer bug in linked list problems?
- Overwriting node.next before saving the rest of the list. In reversal: if you do prev = curr.next AFTER setting curr.next = prev, you've lost the original next node and can't continue the traversal. Always save curr.next to a temp variable as the very first line inside the loop.