Linked List Techniques

Mediumlinked list · pointers · in-place · dummy node · two pointers⏱ 6 min readUpdated

Solve in-place list problems with a small kit of moves - dummy head, iterative reversal, two-pointer gaps and splice-and-merge - while never losing a reference.

PatternLinked List Techniques

Instinct Nodes joined by next pointers and the task is to reverse, splice, merge, reorder or remove in place - grab a dummy head and rewire pointers carefully.

Memory hack Save next, flip, step - never let go of a rope before you've grabbed the next one.

At a glance

When to use it

  • The data is a linked list and you must reverse, reorder or splice it in place
  • The head itself might be removed or replaced
  • You need the n-th node from the end in a single pass
  • Two lists must be merged, added digit by digit or intersected

Key idea

Rewire next pointers instead of copying values, leaning on a dummy head, three-pointer reversal and fixed-gap pointers, so each node is visited once for O(n) time and O(1) extra space rather than O(n) to copy into an array.

Typical complexity

O(n) time, O(1) space

How to spot it If the problem says "linked list" and asks you to reverse, remove, reorder or merge nodes in place, think linked list techniques (dummy node plus pointer rewiring) first.

The instinct

A linked list gives you no random access, so every clever trick comes from rewiring next pointers rather than moving data. Almost every interview question in this family is a remix of four routines: put a dummy node in front of the head, reverse a run of nodes, keep two pointers a fixed gap apart, and merge or splice two chains. If you can write those four from memory without a bug, harder problems become "which routines, in what order?"

Recognise it

Signal in the problem Why it points here
"reverse the list" / "reverse nodes between left and right" / "in groups of k" Iterative three-pointer reversal, possibly on a sub-range.
"remove the n-th node from the end" Lead pointer starts n steps ahead; when it hits the end the trailer is at the target.
"the head itself might be deleted or changed" A dummy node removes the special case.
"reorder / interleave / palindrome check" in O(1) space Find middle, reverse second half, then merge or compare.
"add two numbers stored as digits in nodes" Walk both lists with a carry and build a new chain behind a dummy.
"swap nodes in pairs", "rotate list", "partition list" Pure pointer surgery; draw boxes and arrows first.
"deep copy a list with random pointers" Interleave copies next to originals, or map old -> new.
"find where two lists intersect" Two pointers that switch heads cancel the length difference.

Not this pattern if...

  • You only need to detect a cycle or find a middle - that is the narrower fast & slow pointers pattern.
  • You need O(1) access by index or binary search - copy to an array first, or reconsider the data structure.
  • The problem is about an LRU cache - that is a hash map + doubly linked list design question.

Memory hack

Tip

"Save next, flip, step." Reversal is three moves on repeat: remember where you were going (next = cur.next), turn the arrow around (cur.next = prev), then advance both hands (prev = cur; cur = next).

Analogy: you are a climber on a rope ladder of carabiners. If you unclip one before clipping the next, you fall and the rest of the list is lost to the garbage collector. Every pointer change must happen after you have a handle on what it used to point to.

Say it out loud in the interview:

  1. "I'll add a dummy node so the head is not a special case."
  2. "Before I overwrite any .next, I'll save what it pointed to."
  3. "I'll trace it on 0, 1, 2 and 3 nodes before I say I'm done."

How it works

Treat each problem as a pipeline of standard routines. Reorder List, for example, is three of them chained:

flowchart LR
    A[Find middle with slow and fast] --> B[Cut list after middle]
    B --> C[Reverse second half]
    C --> D[Merge halves alternately]

Reversal trace on 1 -> 2 -> 3 -> null:

Step prev cur next (saved) List state
start null 1 - 1->2->3
1 1 2 2 null<-1 2->3
2 2 3 3 null<-1<-2 3
3 3 null null null<-1<-2<-3

When cur becomes null, prev is the new head.

For Remove Nth Node From End of List, start fast and slow at the dummy, move fast n + 1 steps, then move both until fast is null; slow.next is the node to unlink. Starting at the dummy is what lets you delete the real head.

Java template

java
class ListNode {
    int val;
    ListNode next;
    ListNode(int val) { this.val = val; }
}

class LinkedListKit {
    // Reverse the whole list; returns the new head.
    static ListNode reverse(ListNode head) {
        ListNode prev = null, cur = head;
        while (cur != null) {
            ListNode next = cur.next; // save
            cur.next = prev;          // flip
            prev = cur;               // step
            cur = next;
        }
        return prev;
    }

    // Reverse nodes at positions [left, right] (1-indexed) using a dummy.
    static ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode before = dummy;
        for (int i = 1; i < left; i++) before = before.next;
        ListNode tail = before.next;               // becomes the tail of the reversed part
        for (int i = 0; i < right - left; i++) {   // head-insertion: move tail.next to the front
            ListNode moved = tail.next;
            tail.next = moved.next;
            moved.next = before.next;
            before.next = moved;
        }
        return dummy.next;
    }

    // Remove the n-th node from the end with a fixed gap between two pointers.
    static ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode fast = dummy, slow = dummy;
        for (int i = 0; i <= n; i++) fast = fast.next;
        while (fast != null) { fast = fast.next; slow = slow.next; }
        slow.next = slow.next.next;
        return dummy.next;
    }

    // Merge two sorted lists behind a dummy; reuse for many "build a new chain" problems.
    static ListNode merge(ListNode a, ListNode b) {
        ListNode dummy = new ListNode(0), tail = dummy;
        while (a != null && b != null) {
            if (a.val <= b.val) { tail.next = a; a = a.next; }
            else { tail.next = b; b = b.next; }
            tail = tail.next;
        }
        tail.next = (a != null) ? a : b;
        return dummy.next;
    }
}

Complexity

Routine Time Space
Iterative reverse (whole or sub-range) O(n) O(1)
Recursive reverse O(n) O(n) call stack
Nth-from-end with gap pointers O(n), one pass O(1)
Merge two sorted lists O(n + m) O(1)
Copy with random pointers (interleave) O(n) O(1) besides the copy

Variations

  • Sub-range reversal - reverse only positions left..right: Reverse Linked List II.
  • Group reversal - check k nodes exist, reverse them, reconnect, repeat: Reverse Nodes in k-Group.
  • Gap pointers - lead pointer k ahead: Remove Nth Node From End of List, Rotate List.
  • Split and stitch - build two chains behind two dummies, then join: Partition List, Odd Even Linked List.
  • Middle + reverse + compare/merge - Palindrome Linked List, Reorder List.
  • Arithmetic on digits - carry through two lists: Add Two Numbers.
  • Interleaved cloning - insert each copy after its original: Copy List with Random Pointer.
  • Head switching - two pointers swap to the other list's head at the end: Intersection of Two Linked Lists.

Common mistakes

Warning

Overwriting cur.next before saving it. The rest of the list becomes unreachable and your loop ends early or throws a NullPointerException.

  • Returning head instead of dummy.next after the head was removed or moved.
  • Dereferencing fast.next.next without checking fast != null && fast.next != null.
  • Forgetting to cut the list (set a .next to null) after splitting, which creates an accidental cycle.
  • Off-by-one in gap pointers: the lead must move n + 1 steps from the dummy so slow stops before the target.
  • In k-group reversal, reversing the final short group when the problem says to leave it unchanged.

All practice problems

15 problems on this site use this pattern, easiest first. Solve them in order and say the instinct out loud before you code.

My notes saved in this browser