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 -> ...
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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)