How to Explain Merge Two Sorted Linked Lists in a Coding Interview (Step-by-Step)
Merge Two Sorted Lists is the canonical linked list problem — and the one most likely to expose gaps in pointer fundamentals. The algorithm is simple, but candidates consistently struggle to articulate why a dummy head node is used, what happens when one list runs out, and how to avoid losing track of the merged list’s head.
In this post, you’ll learn exactly how to walk an interviewer through LeetCode 21: the dummy head technique, the iterative compare-and-link loop, the tail-append optimisation for the remaining list, and the elegant recursive solution as a follow-up.
Problem Statement
You are given the heads of two sorted linked lists list1 and list2. Merge the two lists into one sorted list. The list should be made by splicing together the nodes of the first two lists.
Return the head of the merged linked list.
Examples
Output: [1→1→3→4→4→5]
Output: []
Output: [0]
Constraints
- The number of nodes in both lists is in the range
[0, 50] -100 <= Node.val <= 100- Both
list1andlist2are sorted in non-decreasing order
What Is the Problem?
“I’m given two already-sorted linked lists and need to weave them together into a single sorted list — by relinking existing nodes, not creating new ones. The key challenge isn’t the comparison logic; it’s managing pointers carefully so I never lose the head of the merged list or orphan a node.”
Emphasising “relinking existing nodes” signals that you understand memory constraints — you’re not allocating new node objects, just redirecting next pointers. That’s the kind of precision interviewers look for on linked list problems.
Step 1: Compare Approaches Before Jumping to Code
“I’ll walk through the iterative solution as the primary answer — it’s O(1) space and avoids stack overflow risk on long lists. I can then show the recursive version as an elegant alternative if the interviewer wants both.”
The Key Insight — Always Pick the Smaller Head
At every step, compare the current front of list1 and list2. The smaller value must come next in the merged list. Append that node to the tail of the merged result, then advance the pointer in whichever list we just took from. Repeat until one list is exhausted — then append the entire remaining list in one pointer assignment.
The critical design decision is the dummy head node — it gives the tail pointer a valid starting node so the first append doesn’t need a special case.
“Without a dummy head, I’d need a conditional to handle ‘what if the merged list is empty when I try to append?’ The dummy node eliminates that check entirely — tail always points to a valid node and tail.next = node always works.”
The Dummy Head Technique
The merged list’s head is the smallest of the two list heads — but we don’t know which list that is before we start. Without a dummy, we’d have to handle “setting the head for the first time” as a special case separate from all subsequent appends.
The fix: Create a dummy = ListNode(0). Set tail = dummy. Now every append is identically tail.next = node; tail = tail.next. At the end, the real merged head is dummy.next — skipping the dummy itself.
This is one of the most fundamental linked list techniques. Name it explicitly.
Step 2: Explain the Algorithm in Plain English
Allocate one sentinel node dummy = ListNode(0). Set tail = dummy. This is the only node we allocate — all subsequent operations relink existing nodes.
While list1 and list2 are both non-null: compare their values. Attach the smaller node to tail.next, advance tail, and advance whichever list pointer we just consumed.
When one list is exhausted, attach the other list’s remaining pointer directly to tail.next. Since the remaining nodes are already sorted and all larger than what we’ve processed, this is a single O(1) pointer assignment — no loop needed.
dummy.next is the head of the merged sorted list. Return it.
Step-by-Step Visual — list1=[1→4→5], list2=[1→3→4]
Blue = list1 nodes, Purple = list2 nodes, Orange = nodes added to the result so far.
Initial state
Step 3: Talk Through the Iterative Code
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0) # Sentinel — avoids special-casing the head
tail = dummy
while list1 and list2:
if list1.val <= list2.val:
tail.next = list1 # Link the smaller node
list1 = list1.next # Advance list1
else:
tail.next = list2
list2 = list2.next
tail = tail.next # Advance the merged tail
# Append whichever list still has nodes — O(1), not a loop
tail.next = list1 if list1 else list2
return dummy.next # Skip the dummy sentinel
Three details worth narrating: (1) tail.next = list1 relinks the existing node — no new allocation; (2) tail = tail.next must come after the assignment, not before; (3) tail.next = list1 if list1 else list2 replaces an entire loop — the remaining nodes are already sorted and already linked, so one pointer assignment appends all of them.
The Recursive Solution — Elegant Alternative
The recursive solution is beautifully concise. Each call picks the smaller head, sets its next to the result of merging the remaining nodes recursively, and returns the smaller head. Base cases handle empty lists.
Worth knowing, but mention the O(n+m) stack depth — for lists of length 50 this is fine, but for very long lists the iterative approach is safer.
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
# Base cases: if either list is empty, return the other
if not list1: return list2
if not list2: return list1
if list1.val <= list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list1, list2.next)
return list2
"The recursive version is O(n+m) time and O(n+m) space due to the call stack. For this problem's constraints (max 50 nodes each) it's perfectly fine. If asked to handle arbitrarily long lists, the iterative approach is strictly better."
Step 4: Highlight Edge Cases
"Bothlist1andlist2are null. The while loop never executes.tail.next = null. Returndummy.next = null. Correct."
"The while condition fails immediately.tail.next = list2(the non-empty list). Returndummy.nextwhich points to the head of list2. Correct — no iteration needed."
"If list1 = [1,2,3] and list2 = [4,5,6], we drain list1 entirely in the while loop, then tail.next = list2 appends all of list2 at once. No extra comparisons — O(1) final step."
"The condition is<=, so equal values from list1 are taken first. Either choice is correct — the problem only requires sorted output, not stable ordering. The<=avoids infinite loops that<could cause on equal values."
"One iteration of the while loop, one tail-append. Result is a two-node list. Handled correctly with no special casing."
Step 5: State Time and Space Complexity
| Dimension | Iterative | Recursive | Reason |
|---|---|---|---|
| Time | O(n+m) | O(n+m) | Every node from both lists is visited exactly once |
| Space | O(1) | O(n+m) | Iterative: only two pointers. Recursive: call stack depth equals total nodes |
"Both approaches are O(n+m) time — every node is touched exactly once. The difference is space: iterative uses O(1) extra memory (just the dummy node and two pointers); recursive uses O(n+m) stack frames. For the problem's constraint of 50 nodes each, both are fine. For general use, iterative is the safer production choice."
Interview Checklist for Merge Two Sorted Linked Lists
- Restate — "weave two sorted lists by relinking nodes, not creating new ones"
- Mention the collect-into-array approach and explain why it wastes the sorted property
- Name and explain the dummy head technique — why it removes the head-initialisation special case
- Describe the tail pointer — it always points to the last node of the merged result
- Use
<=not<for the comparison — handles equal values correctly - Explain the tail-append at the end — one pointer assignment, not a loop
- Return
dummy.next, notdummy - Offer the recursive solution and state the O(n+m) stack space tradeoff
- Call out edge cases: both empty, one empty, one list fully smaller, duplicates
- State O(n+m) time and O(1) space for iterative; O(n+m) space for recursive
Related Problems to Practice
If you can solve Merge Two Sorted Lists cleanly, try these next:
