150NeetCode 150

36.Merge Two Sorted Lists

EasyBlind 75Linked List ยท 2/11

Problem

You are given the heads of two linked lists, list1 and list2, each sorted in non-decreasing order.

Merge them into one sorted list by splicing together the existing nodes (no new value nodes needed) and return the head of the merged list.

Examples

Input:  list1 = [1, 2, 4], list2 = [1, 3, 4]
Output: [1, 1, 2, 3, 4, 4]
Explanation: Repeatedly take the smaller front node from the two lists.
Input:  list1 = [], list2 = []
Output: []
Input:  list1 = [], list2 = [0]
Output: [0]
Explanation: If one list is empty, the answer is simply the other list.

Constraints

  • The number of nodes in both lists is in the range [0, 50].
  • -100 <= Node.val <= 100
  • Both list1 and list2 are sorted in non-decreasing order.

๐Ÿ’ก Key Insight

Because both lists are already sorted, the smallest remaining element is always at the front of one of the two lists. Compare the two fronts, attach the smaller one, and advance that list โ€” the same "merge" step used in merge sort. A dummy head node removes all special-casing for the first node.

Brute Force (Collect and Sort)

TimeO((n + m) log(n + m))SpaceO(n + m)

Intuition

Ignore the fact that the inputs are sorted: dump every node into a list, sort by value, and relink them in order.

Algorithm

  1. Walk both lists and add every node to an ArrayList.
  2. Sort the nodes by val.
  3. Link nodes[i].next = nodes[i + 1], and set the last node's next to null.
  4. Return nodes[0] (or null if there are no nodes).

Visualization

list1: 1 -> 2 -> 4      list2: 1 -> 3 -> 4
collected: [1, 2, 4, 1, 3, 4]
sorted:    [1, 1, 2, 3, 4, 4]
relinked:  1 -> 1 -> 2 -> 3 -> 4 -> 4 -> null

Code

java
import java.util.ArrayList;
import java.util.List;

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        List<ListNode> nodes = new ArrayList<>();
        for (ListNode n = list1; n != null; n = n.next) nodes.add(n);
        for (ListNode n = list2; n != null; n = n.next) nodes.add(n);
        if (nodes.isEmpty()) {
            return null;
        }
        nodes.sort((a, b) -> Integer.compare(a.val, b.val));
        for (int i = 0; i + 1 < nodes.size(); i++) {
            nodes.get(i).next = nodes.get(i + 1);
        }
        nodes.get(nodes.size() - 1).next = null; // terminate the merged list
        return nodes.get(0);
    }
}

Complexity

  • Time: O((n + m) log(n + m)) โ€” sorting all nodes.
  • Space: O(n + m) โ€” the auxiliary list of nodes.

Complexity Comparison

Approach Time Space
Collect and Sort O((n+m) log(n+m)) O(n+m)
Recursion O(n+m) O(n+m)
Iterative with Dummy Head O(n+m) O(1)

Common Pitfalls

  • Forgetting to attach the leftover list after the loop โ€” you would drop the tail of one input.
  • Forgetting to advance tail after attaching a node, so every node overwrites the same tail.next.
  • Returning dummy instead of dummy.next, which adds a bogus 0 at the front.
  • Not handling empty inputs; with a dummy head, two null lists naturally return null.
  • Using < versus <= does not affect correctness here, but <= keeps the merge stable (equal values from list1 come first).