DEV Community

Dev Cookies
Dev Cookies

Posted on

A Complete Guide to Mastering Linked-List Problems

Linked lists look simple, but one wrong pointer and the whole chain collapses.
A single trick—the dummy (sentinel) node pattern—can simplify almost every tricky linked-list algorithm.

This blog explains:

  • ✅ Why dummy nodes make life easier
  • ✅ Core pointer-change techniques
  • ✅ Multiple classic problems solved with clean Java code
  • ✅ Edge-case analysis and complexity notes

1️⃣ Why a Dummy Node?

A dummy node is an extra node you insert at the front:

dummy -> head -> ...
Enter fullscreen mode Exit fullscreen mode

It is not part of the real data but provides a guaranteed non-null node before the head.

Benefits

  • Unified logic: You never need to ask, “Am I deleting the head?”
  • Simpler pointer updates: Every operation has a valid predecessor.
  • Safer code: Reduces null-pointer checks and off-by-one mistakes.

2️⃣ Core Pointer-Change Moves

All dummy-node algorithms are built from a few pointer patterns:

Pattern Purpose Java Skeleton
Find Predecessor Move to the node just before target while (count < k) prev = prev.next;
Splice/Delete Remove a node prev.next = prev.next.next;
Insert After Add node after prev node.next = prev.next; prev.next = node;
Head Insertion Reverse a segment in place next.next = prev.next; prev.next = next;

Memorize these and most linked-list problems become mechanical.


3️⃣ Classic Problems & Solutions

Below are seven staple problems, each solved with the dummy-node technique.


A. Remove Nth Node from End

Idea: Two-pointer technique with a dummy.

class Solution {
    public 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.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }
}
Enter fullscreen mode Exit fullscreen mode

Time: O(n) Space: O(1)


B. Reverse a Sub-List (Left..Right)

Pattern: Head-insertion.

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;

        for (int i = 1; i < left; i++) prev = prev.next;
        ListNode curr = prev.next;

        for (int i = 0; i < right - left; i++) {
            ListNode next = curr.next;
            curr.next = next.next;
            next.next = prev.next;
            prev.next = next;
        }
        return dummy.next;
    }
}
Enter fullscreen mode Exit fullscreen mode

C. Merge Two Sorted Lists

Attach nodes to a tail pointer starting from a dummy.

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;

        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                tail.next = l1;
                l1 = l1.next;
            } else {
                tail.next = l2;
                l2 = l2.next;
            }
            tail = tail.next;
        }
        tail.next = (l1 != null) ? l1 : l2;
        return dummy.next;
    }
}
Enter fullscreen mode Exit fullscreen mode

D. Partition List Around a Value x

Maintain two dummy heads, then join.

class Solution {
    public ListNode partition(ListNode head, int x) {
        ListNode beforeDummy = new ListNode(0), afterDummy = new ListNode(0);
        ListNode before = beforeDummy, after = afterDummy;

        while (head != null) {
            if (head.val < x) {
                before.next = head;
                before = head;
            } else {
                after.next = head;
                after = head;
            }
            head = head.next;
        }
        after.next = null;
        before.next = afterDummy.next;
        return beforeDummy.next;
    }
}
Enter fullscreen mode Exit fullscreen mode

E. Remove Duplicates from Sorted List (II)

Delete all nodes that have duplicates.

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;

        while (head != null) {
            boolean dup = false;
            while (head.next != null && head.val == head.next.val) {
                dup = true;
                head = head.next;
            }
            if (dup) prev.next = head.next;
            else prev = prev.next;
            head = head.next;
        }
        return dummy.next;
    }
}
Enter fullscreen mode Exit fullscreen mode

F. Rotate Right by k Places

Convert to a ring, then break at the correct place.

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || head.next == null) return head;
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        // find length & tail
        int len = 1;
        ListNode tail = head;
        while (tail.next != null) { tail = tail.next; len++; }
        k %= len;
        if (k == 0) return head;

        // move to new tail
        ListNode newTail = dummy;
        for (int i = 0; i < len - k; i++) newTail = newTail.next;

        ListNode newHead = newTail.next;
        newTail.next = null;
        tail.next = head;
        return newHead;
    }
}
Enter fullscreen mode Exit fullscreen mode

G. Swap Nodes in Pairs

Pairs are swapped with pointer juggling and a dummy.

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;

        while (head != null && head.next != null) {
            ListNode first = head;
            ListNode second = head.next;

            prev.next = second;
            first.next = second.next;
            second.next = first;

            prev = first;
            head = first.next;
        }
        return dummy.next;
    }
}
Enter fullscreen mode Exit fullscreen mode

4️⃣ Edge-Case Checklist

Whenever you write a linked-list algorithm, test:

  • Empty list (head == null)
  • Single node
  • Operation affects the first node
  • Operation affects the last node
  • Duplicates or equal values if relevant

The dummy node simplifies all of these.


5️⃣ Key Takeaways

  • Add a dummy node at the start of almost any linked-list algorithm.
  • Master these moves: Find predecessor → Splice/Delete → Insert After → Head Insertion.
  • Complexity for all examples: O(n) time, O(1) extra space.

Pro Tip: Even if you could code without a dummy node, using one makes your solution more readable and less error-prone.


By internalizing this pattern, you’ll have a reusable blueprint for virtually every linked-list manipulation problem—from interview puzzles to production systems.

Top comments (0)