LeetCode 203: Remove Linked List Elements - Mastering the Dummy Head Pattern
A deep dive into solving linked list deletion problems, comparing approaches with and without dummy head nodes, including my mistakes and key takeaways.
The most important concept in this problem is understanding how to use a dummy head node. It is a powerful technique for linked list problems, because it simplifies edge cases and unifies the logic.
Problem Statement
Given the head of a singly linked list and an integer val, remove all the nodes of the linked list that have val equal to the given value, and return the new head.
Approach 1: Without Dummy Head (Straightforward but More Complex)
var removeElements = function (head, val) {
  while (head !== null && head.val === val) {
    head = head.next;
  }
  let cur = head;
  while (cur !== null && cur.next !== null) {
    cur.next.val === val ? (cur.next = cur.next.next) : (cur = cur.next);
  }
  return head;
};Thought Process
- Start by removing leading nodes that match the target value.
 - Then traverse the list with a pointer 
cur. - At each step, check 
cur.next. If it matches the value, skip it; otherwise, advance. 
Characteristics
- Correct and intuitive, but requires separate handling for the head node(s).
 - Slightly less elegant because of the special-case loop at the beginning.
 
Approach 2: With Dummy Head (Cleaner and Uniform)
var removeElements = function (head, val) {
  let dummyHead = new ListNode(0, head);
  let cur = dummyHead;
  while (cur.next !== null) {
    cur.next.val === val ? (cur.next = cur.next.next) : (cur = cur.next);
  }
  return dummyHead.next;
};Thought Process
- Create a dummy head pointing to the original 
head. - Use a pointer 
curstarting from the dummy head. - Always check 
cur.next: if it matches, skip it; if not, move forward. - Finally, return 
dummyHead.nextas the new head. 
Characteristics
- No special treatment for the head node.
 - Unified logic for head, middle, and tail.
 - This pattern is widely considered the canonical solution for linked list deletion problems.
 
My Mistaken Attempt
var removeElements = function (head, val) {
  let dummyHead = new ListNode(0, head);
  let cur = head;
  while (cur !== null) {
    cur.val === val ? (dummyHead.next = cur.next) : (cur = cur.next);
  }
  return dummyHead.next;
};What I Was Thinking
- I believed that since 
dummyHeadalready connects tohead, I could always handle deletions by simply reassigningdummyHead.next. - I therefore set 
cur = headand attempted to modifydummyHead.nextwhenever a match was found. 
Why This Was Wrong
- Lost the predecessor: 
dummyHeadcan only help when deleting the actual head. For middle nodes, you must reconnect from their immediate predecessor. - Infinite loop risk: In the delete branch, 
curdid not advance, so the loop could get stuck. - Over-reliance on dummyHead: I misunderstood its role. A dummy node does not "delete everything for you"; it just provides a consistent starting point.
 
Reflection
- My error came from a misconception about dummy head usage. I thought it could act as a universal pointer for all deletions, when in reality, it only ensures we have a safe and consistent starting node.
 - The correction was simple but fundamental: move the traversal pointer to start at 
dummyHead, always checkcur.next, and advance correctly. - Once I applied this, the logic became uniform and robust, handling head, middle, and tail cases seamlessly.
 
Key Takeaways
- Without dummy head: The solution works but requires special handling of the head node.
 - With dummy head: The solution is more elegant, with a unified approach that removes all edge cases.
 - Personal lesson: A dummy head is not magic. It is a tool that simplifies pointer management — but only if you maintain the correct predecessor during traversal.
 - Best practice: In linked list problems involving insertion or deletion, always consider introducing a dummy head. It makes the code cleaner and reduces the chance of subtle bugs.
 
For a deeper understanding of the dummy head pattern and how it applies to many other algorithmic problems, check out The Dummy Head Design Pattern: Beyond Linked Lists.