beginner7 min read·Updated September 23, 2026

Merge Two Sorted Linked Lists Explained: Tracing 1→2→4 and 1→3→4

Master merging sorted linked lists. Follow a complete mental model, trace 1→2→4 and 1→3→4 step by step, and handle edge cases clearly.

By Learnisim AI·Published September 23, 2026
LEARNING ARCSetup → Model in the example → Full trace → Twist → Edge cases → Apply
PREREQUISITES
  • Basic pointer navigation
  • Understanding singly linked lists
Merging Two Sorted Linked Lists (In-Place Pointer Splice) Input: list1 (1→2→4) and list2 (1→3→4) | Goal: Produce 1→1→2→3→4→4 without extra memory Source Sequences (Input) list1: 1 2 4 list2: 1 3 4 p1 → 1 p2 → 1 Mental Model: Dummy Node & Tail dummy(0) tail • Prevents edge cases on first attachment • O(1) extra space Step-by-Step Pointer Splice Trace Step 1: Compare p1(1) & p2(1) • Equal! Take list1's node (1) • tail.next = p1 • p1 steps to 2 0 1 tail → 1 Step 2: Compare p1(2) & p2(1) • p2.val (1) < p1.val (2) • tail.next = p2 • p2 steps to 3 0 1 1 tail → second 1 Step 3: Compare p1(2) & p2(3) • p1.val (2) < p2.val (3) • tail.next = p1 (2) • p1 advances to 4 Chain: 0→1→1→2 Then 3 spliced next! Step 4: Tail Attachment • One list runs out first • Attach remaining tail directly • Return dummy.next Result: 1 → 1 → 2 → 3 → 4 → 4 Key Takeaway: Direct pointer manipulation avoids extra allocations, achieving O(N + M) time and O(1) space complexity.
Merge 1→2→4 and 1→3→4 overview diagram
Why

Why Merge Two Sorted Linked Lists?

Phase 1: The Sequencing Bottleneck

Imagine you are handed two separate chains of data that are already sorted in ascending order. For our locked working example, we have list1 starting at node and list2 starting at node . If you need to combine them into a single sorted stream, your first instinct might be to unpack everything into an array, sort it from scratch, and rebuild a brand new linked list. But that wastes time and memory.
Linked lists give us a superpower: individual nodes can be re-routed instantly by updating pointers, provided we know how to weave them together in order. Without a systematic strategy, you risk losing track of tail references, breaking chain connections, or getting stuck trying to compare unsorted chunks. We want to arrive at our expected final result, , by directly stitching the existing nodes together in a single pass.
javascript
// Given setup for our locked example:
// list1: 1 -> 2 -> 4
// list2: 1 -> 3 -> 4
// Goal: produce 1 -> 1 -> 2 -> 3 -> 4 -> 4 without allocating new nodes.
Why Merge Two Sorted Linked Lists? Direct pointer re-routing: stitch 1→2→4 and 1→3→4 into 1→1→2→3→4→4 in-place without new allocations list1 (Head) 1 2 4 list2 (Head) 1 3 4 Compare & Re-weave Pointers Final Merged Result: 1 → 1 → 2 → 3 → 4 → 4 (In-place pointer rewiring) 1 (list1) 1 (list2) 2 (list1) 3 (list2) 4 (list1) 4 (list2) O(N + M) Time & O(1) Space Single pass comparison visiting every node once without extra arrays. Zero Memory Allocation Re-routes existing .next pointers instantly instead of rebuilding nodes. Dummy Head Strategy Prevents edge cases when establishing the new combined head pointer.
Why Merge Two Sorted Linked Lists? diagram
Model

Mental Model: Pointers and the Dummy Node

Phase 2: The Pointer & Dummy Model

When we want to combine list1 () and list2 () without allocating new nodes, we cannot use standard array indexing. Instead, we use a single sliding pointer—often named tail—to stitch the existing nodes together in ascending order.
To simplify the logic of attaching the very first node, we introduce a dummy head node. This temporary anchor gives our tail pointer a reliable starting point, so we never have to write special conditional code for the first successful comparison.
As our pointers advance through the sequences, we compare the current value of list1 against list2. Whichever value is smaller gets linked to tail.next, and that list's pointer steps forward while tail advances to follow it.
Merge Two Sorted Lists: Pointers & The Dummy Node Stitching existing nodes in ascending order without allocating new memory Input Lists list1: 1 2 4 list2: 1 3 4 Why use a Dummy Node? • Avoids special conditional checks for attaching the 1st node • Provides a reliable starting anchor for the sliding tail pointer Result: head = dummy.next returns the clean merged chain Sliding Tail Pointer & Stitching Process (Active State) Comparing current nodes: smaller value attaches to tail.next, pointer advances. dummy -1 head ref node 1 node 1 node 2 node 3 node 4 node 4 tail null Loop invariant: tail always points to the last appended node of the merged result. When one list empties, attach the remainder of the other list instantly via tail.next.
Mental Model: Pointers and the Dummy Node diagram
Worked example

Walking the Pointers: A Step-by-Step Merge Trace

Phase 3: Step-by-Step Trace

To see our mental model in action, let us trace through the locked working example with and . We initialize a node with value 0 and set our pointer equal to . Let point to the head of (1) and point to the head of (1).

Step 1: Comparing the First Nodes

Both (1) and (1) are equal. By convention, we can take from first. We attach to , advance to , and advance to 2.
- Intermediate State: (from )
- Active Pointers: , ,

Step 2: Comparing Next Nodes

Now we compare (2) with (1). Since , we attach to , advance to , and advance to 3.
- Intermediate State: (second 1 from )
- Active Pointers: ('s first node), ,

Step 3: Continuing the Comparison Loop

Comparing (2) and (3): , so we attach (2), advance to , and advance to 4.
- Intermediate State:
- Active Pointers: , ,
Next, comparing (4) and (3): , so we attach (3), advance to , and advance to 4.
- Intermediate State:
- Active Pointers: , ,

Step 4: Finalizing Remaining Nodes

Both and now sit at value 4. Comparing them yields a tie; we take (4), advance and (so becomes ). Then, since still holds a final node (4), we attach the remainder of directly to .
- Result: yields the fully merged sorted list: .
Try this: Given list1 = 1->2->4 and list2 = 1->3->4, what is the exact node value attached to tail.next during Step 3 when comparing p1.val (2) and p2.val (3)?
Walking the Pointers: Step-by-Step Trace list1 = 1→2→4 | list2 = 1→3→4 | Focus: Comparing & Stepping through the Trace list1: 1 2 4 p1 list2: 1 3 4 p2 merged result (dummy & tail): 0 1 1 2 dummy tail Phase 3 Trace State (Step 3) Comparing p1.val (2) & p2.val (3): • Since 2 < 3, we pick p1's node (val 2) • Attach p1 to tail.next • Advance tail to new node (2) • Advance p1 forward to value 4 Intermediate State: dummy → 1 → 1 → 2 Try this: What node value is attached to tail.next during this comparison? Answer: 2 (from p1)
Walking the Pointers: A Step-by-Step Merge Trace diagram
Apply

Applying the Pointer-Splice Pattern to New Challenges

Phase 4: Apply

Now that you have seen how a dummy head and advancing pointers successfully weave list1 = 1→2→4 and list2 = 1→3→4 into 1→1→2→3→4→4 by reusing existing nodes in time, it is time to transfer this pattern. The core lesson of the merge routine is not just about sorting; it is about structural pointer redirection where you never allocate new nodes, but instead rewire existing .next references in a single pass.
Consider what happens if we change the target slightly. Suppose instead of merging two sorted lists, you are given sorted linked lists, or you need to merge two sorted lists where one list contains duplicate values that you want to filter out on the fly. The dummy node anchor and the tracking tail pointer remain your primary tools because they prevent you from losing the head of the newly formed sequence. Whenever you manipulate sorted linked lists, always ask: Where is my immutable entry point, and which pointer is currently responsible for attaching the next smallest element?
python
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def mergeTwoLists(list1: ListNode, list2: ListNode) -> ListNode:
    dummy = ListNode(-1)
    tail = dummy
    # Implement the merge loop using list1 and list2
    return dummy.next

FAQ

How do we merge the specific lists 1→2→4 and 1→3→4?
We use two pointers to compare the heads. Starting with both lists at 1, we pick the first 1, then the second 1, then 2 from list1, then 3 from list2, followed by the remaining 4s, resulting in 1→1→2→3→4→4.
What is the time and space complexity of merging two sorted linked lists?
The time complexity is O(n + m), where n and m are the lengths of the two lists, because we traverse each node at most once. The space complexity is O(1) if we rearrange pointers in place using a dummy node.
Why use a dummy node for this algorithm?
A dummy node acts as a permanent anchor for the start of the new merged list, eliminating special-case logic for initializing the head pointer.
What are common pitfalls when merging linked lists?
Common mistakes include losing track of remaining nodes after one list becomes null, failing to update pointer links correctly, and not handling empty input lists.

Keep learning