DSA Tracker

Easy

Merge Two Sorted Lists

An easy Linked List problem included in Apna College, Love Babbar 450, Striver A2Z. Below: the roles whose interviews prioritise this topic, and how to practise it.

Topic
Linked List
Sheets
3
Core for
3 roles
Platform
LeetCode

The problem

Merge two sorted linked lists into one sorted linked list by splicing together the nodes.

Example 1

Input
list1=[1,2,4], list2=[1,3,4]
Output
[1,1,2,3,4,4]

Example 2

Input
list1=[], list2=[]
Output
[]

Example 3

Input
list1=[], list2=[0]
Output
[0]

Constraints

  • 0 <= list1.length, list2.length <= 50
  • -100 <= Node.val <= 100

How to think about it

Updated 2026-09-09

Because both chains are already ordered, the global minimum is always sitting at one of the two current heads. Splice the smaller node into your merged chain and you never need to examine or reallocate the interior of either list.

Approaches, worst first

  1. Recursive splice

    time O(n + m) · space O(n + m)

    Compare the two heads and set the smaller node's next pointer to the result of recursively merging its suffix with the other list. Compact and expressive, but builds call frames proportional to the total number of elements.

  2. Dummy sentinel with iterative spliceWrite this one

    time O(n + m) · space O(1)

    Anchor the result with a dummy node and walk a tail pointer forward. At each step, attach whichever head has the smaller value and advance that input list. Once either list empties, splice the non-empty remainder in a single O(1) pointer assignment.

Where people lose marks · 3
  • Trying to append remaining nodes one-by-one inside a trailing loop instead of wiring the remaining non-empty sublist directly with `tail.next = l1 || l2`.
  • Failing to use a dummy sentinel node forces messy branching to assign the new head on the very first step before normal iteration can begin.
  • Handling empty inputs as special case crashes unless null checks guard the initial dereference of list1.val and list2.val.

Full solution

Dummy sentinel with iterative splice: walk both lists once, always attach the smaller head, then wire the non-empty remainder in one O(1) assignment. Same O(n+m) time as the recursive version but O(1) space instead of a call frame per node.

Python
class ListNode:
    def __init__(self, val: int = 0, next: "ListNode | None" = None):
        self.val = val
        self.next = next


def merge_two_lists(list1: "ListNode | None", list2: "ListNode | None") -> "ListNode | None":
    dummy = ListNode()
    tail = dummy
    while list1 and list2:
        if list1.val <= list2.val:
            tail.next = list1
            list1 = list1.next
        else:
            tail.next = list2
            list2 = list2.next
        tail = tail.next
    # one list is exhausted - the other's remainder is already sorted, splice it whole
    tail.next = list1 if list1 else list2
    return dummy.next
JavaScript
class ListNode {
  constructor(val = 0, next = null) {
    this.val = val;
    this.next = next;
  }
}

function mergeTwoLists(list1, list2) {
  const dummy = new ListNode();
  let tail = dummy;
  while (list1 && list2) {
    if (list1.val <= list2.val) {
      tail.next = list1;
      list1 = list1.next;
    } else {
      tail.next = list2;
      list2 = list2.next;
    }
    tail = tail.next;
  }
  // one list is exhausted - the other's remainder is already sorted, splice it whole
  tail.next = list1 ? list1 : list2;
  return dummy.next;
}
Try it in the editor

The theory behind it

Linked List — the ground this problem stands on. All Linked List problems

What Linked List is

A linked list is a chain of separate cargo cars connected by coupling hooks, scattered anywhere across memory rather than sitting in a tidy contiguous row. Each car, called a node, holds a single piece of data and a pointer directing traffic to the address of the next car in line. Because nodes connect only by directional links, jumping straight to the tenth car is impossible without walking past the first nine.

When to reach for it

Choose a linked list when a problem requires frequent insertions and deletions at known positions without shifting whole blocks of surrounding memory. Problems mentioning pointer splicing, reversing subsequences in place, merging sorted streams, or detecting cycles in linear chains strongly point here. It is ideal when total capacity is unpredictable and memory allocation must happen one individual node at a time.

How the pattern works

Think in terms of pointer rewiring before dereferencing. Keep a dummy head node pointing to the start of the list so modifications to the initial item do not require separate edge logic. Always save references to neighboring nodes into temporary variables before cutting or redirecting forward links. When diagnosing loops or locating middle nodes, advance two references simultaneously at differing velocities so traversal completes without supplementary storage.

What each operation costs

OperationTime
insert or delete at the headO(1)
insert or delete after a known nodeO(1)
find an element by value or positionO(n)
What usually goes wrong with Linked List
  • Losing access to the remainder of the chain by overwriting a next reference before caching the downstream node address in a temporary variable.
  • Attempting to read properties of a null node reference after walking one step beyond the tail or advancing a fast runner without checking its next step.
  • Creating an accidental infinite cycle by pointing a trailing node back into earlier segments of the chain without severing old outgoing links.

Which roles need this problem

Linked List is a core topic for these 3 roles — if you're targeting one of them, this problem is early in your path, not optional.

Secondary for 5 more roles, including Full-Stack Developer, Android Developer, iOS Developer.

Track this in your role's order

Pick your target role and all 370 problems — including this one — resequence to what that interview actually asks. Free.

Start free

More Linked List problems

Problem set and role mapping as of .