{x}
blog image

Merge Two Sorted Lists

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.

 

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:

  • 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.

Solution Explanation for Merge Two Sorted Lists

This problem involves merging two sorted linked lists into a single sorted linked list. We'll explore two approaches: recursion and iteration.

Approach 1: Recursion

This approach elegantly solves the problem using recursion. The core idea is to compare the heads of the two input lists (list1 and list2). The smaller head is chosen to be the head of the merged list, and the function recursively calls itself to merge the remaining parts of the two lists.

Algorithm:

  1. Base Cases: If either list1 or list2 is empty, return the non-empty list (or null if both are empty).
  2. Recursive Step:
    • If list1.val <= list2.val, recursively merge list1.next and list2. The result becomes the next node of list1. Return list1.
    • Otherwise, recursively merge list1 and list2.next. The result becomes the next node of list2. Return list2.

Time Complexity: O(m + n), where 'm' and 'n' are the lengths of the two input lists. Each node is visited once.

Space Complexity: O(m + n) in the worst case due to the recursive call stack depth, which can be equal to the length of the longer list.

Approach 2: Iteration

This approach uses an iterative method, making it more efficient in terms of space complexity compared to the recursive approach.

Algorithm:

  1. Create a dummy node (dummy) to simplify the handling of the merged list's head.
  2. Initialize a current pointer (curr) to the dummy node.
  3. Iterate while both list1 and list2 are not empty:
    • Compare list1.val and list2.val.
    • Add the smaller node to curr.next and advance the corresponding list pointer.
    • Move curr to the newly added node.
  4. After the loop, one list might have remaining nodes. Append these nodes to curr.next.
  5. Return dummy.next (the head of the merged list).

Time Complexity: O(m + n). Each node is visited once.

Space Complexity: O(1). Constant extra space is used regardless of input size.

Code Examples (Python)

Recursive Approach:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
 
def mergeTwoListsRecursive(list1, list2):
    if not list1:
        return list2
    if not list2:
        return list1
    if list1.val <= list2.val:
        list1.next = mergeTwoListsRecursive(list1.next, list2)
        return list1
    else:
        list2.next = mergeTwoListsRecursive(list1, list2.next)
        return list2
 

Iterative Approach:

def mergeTwoListsIterative(list1, list2):
    dummy = ListNode()
    curr = dummy
    while list1 and list2:
        if list1.val <= list2.val:
            curr.next = list1
            list1 = list1.next
        else:
            curr.next = list2
            list2 = list2.next
        curr = curr.next
    curr.next = list1 or list2  # Append remaining nodes
    return dummy.next
 

The iterative approach is generally preferred because of its better space complexity. However, the recursive solution is often considered more concise and easier to understand for those comfortable with recursion. Choose the approach that best suits your needs and coding style. The code examples in other languages will follow a similar structure to these Python examples.