Skip to content

21. Merge Two Sorted Lists

Problem Description

LeetCode Problem 21: 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.

Clarification

  • Two lists may have different length. May be empty
  • Two lists are sorted
  • Merge nodes or merge values

Assumption

Solution

Approach 1: Iteration

Start with a dummy head and then compare list1 and list 2 one node at a time. Add nodes with smaller value to the list. Need to handle situation where either list 1 or list 2 ends first.

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        dummy_head = ListNode(-1, None)

        p = dummy_head
        while list1 or list2:
            if list1 is None:
                p.next = list2
                list2 = list2.next
            elif list2 is None:
                p.next = list1
                list1 = list1.next
            else:
                if list1.val <= list2.val:
                    p.next = list1
                    list1 = list1.next
                else:
                    p.next = list2
                    list2 = list2.next

            p = p.next

        return dummy_head.next
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

        // Handle corner case
        if (l1 == null && l2 == null) return null;
        if (l1 == null) return l2;
        if (l2 == null) return l1;

        ListNode dummyHead = new ListNode(-1);
        ListNode p = dummyHead; // pointer for the new linked list starting from dummy head
        ListNode p1 = l1; // pointer for l1 linked list
        ListNode p2 = l2; // pointer for l2 linked list

        while (p1 != null || p2 != null) {
            if (p1 == null) {
                p.next = p2;
                p2 = p2.next;
            }
            else if (p2 == null) {
                p.next = p1;
                p1 = p1.next;
            }
            else {
                if (p1.val <= p2.val) {
                    p.next = p1;
                    p1 = p1.next;
                }
                else {
                    p.next = p2;
                    p2 = p2.next;
                }
            }

            p = p.next;
        }

        return dummyHead.next;

    }
}

Complexity Analysis

  • Time complexity: \(O(n + m)\)
    The number of iterations of the while loop equals to the sum of the lengths of the two lists, \(n + m\).
  • Space complexity: \(O(1)\)
    Only use several pointers.

Approach 2: Recursion

This problem can also be solved using recursion.

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        # Base case
        if list1 is None:
            return list2

        if list2 is None:
            return list1

        # Recursion
        if list1.val <= list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1
        else:
            list2.next = self.mergeTwoLists(list1, list2.next)
            return list2
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // Base case:
        if (l1 == null) return l2;
        if (l2 == null) return l1;

        // Recursively break down problem into a smaller one
        if (l1.val <= l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        }
        else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }

    }
}

Complexity Analysis of Approach 2

  • Time complexity: \(O(n + m)\)
    It will go through both lists (total \(n + m\) nodes) one node at a time.
  • Space complexity: \(O(n + m)\)
    Auxiliary stack space due to recursive function calls. The recursive function will be called \(n + m\) times.

Comparison of Different Approaches

The table below summarize the time complexity and space complexity of different approaches:

Approach Time Complexity Space Complexity
Approach - iteration \(O(n + m)\) \(O(1)\)
Approach - recursion \(O(n + m)\) \(O(n + m)\)

Test