Merge Two Sorted Lists - Complete Solution Guide
Merge Two Sorted Lists is LeetCode problem 21, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
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.v
Detailed Explanation
You're presented with two linked lists, `list1` and `list2`, both already sorted in non-decreasing order. The task isn't just to combine them, but to interweave their nodes to form a *single, new* sorted linked list. Crucially, the problem specifies 'splicing together the nodes,' implying we should reuse the existing nodes rather than creating entirely new ones and copying values over. Think of it like merging two sorted decks of cards into one sorted deck, carefully picking the lowest card available from either pile at each step.
Solution Approach
The provided solution employs an elegant iterative approach using a 'dummy' node and a 'tail' pointer. We initialize a `dummy` node (its value doesn't matter, it's just a placeholder) and a `tail` pointer, which initially points to `dummy`. This `dummy` node is a common trick in linked list problems; it simplifies the logic by giving us a consistent node to attach new elements to, avoiding special-casing when the merged list is empty. We then enter a loop that continues as long as both `list1` and `list2` have nodes. Inside the loop, we compare the `val` of the current nodes in `list1` and `list2`. The node with the smaller value is appended to `tail.next`, and then the pointer of the list from which that node was taken is advanced (`list1 = list1.next` or `list2 = list2.next`). Regardless of which node was chosen, `tail` is then advanced to point to the newly appended node, preparing for the next attachment. Once one of the lists becomes empty, the loop terminates. At this point, the *entire remainder* of the other list (if any) is already sorted and simply needs to be appended to the `tail` of our merged list. Finally, we return `dummy.next`, as `dummy` itself was just a starting placeholder.
Step-by-Step Algorithm
- Step 1: Create a dummy node and initialize a tail pointer to it. This dummy node simplifies handling the head of the merged list.
- Step 2: Iterate while both `list1` and `list2` are not empty. Compare the values of the current nodes in `list1` and `list2`.
- Step 3: Append the node with the smaller value to the tail of the merged list by setting `tail.next` to that node. Then, advance the pointer of the list from which the node was taken.
- Step 4: Update the tail pointer to point to the newly added node.
- Step 5: After one of the lists is empty, append the remaining nodes from the other list to the tail of the merged list.
- Step 6: Return the `next` of the dummy node (the actual head of the merged list).
Key Insights
- **The Dummy Node Tactic:** Using a `dummy` node as a head placeholder for the merged list simplifies initial node placement. It ensures `tail` always points to a valid node, even when the merged list is empty, allowing a consistent `tail.next = ...` operation without needing to check if `head` is null.
- **Greedy Iterative Splicing:** The core idea is to iteratively compare the heads of the remaining `list1` and `list2`, 'greedily' appending the smaller node to the end of our growing merged list. We then advance *only* the pointer of the list from which we took the node, ensuring we always consider the smallest available element for the next step.
- **Efficient Remainder Appending:** Once one input list is exhausted, the entire remaining portion of the other list can be appended directly to the end of the merged list in a single step (`tail.next = list1` or `tail.next = list2`). This works because the remaining list is already sorted, and there are no more elements from the other list to interleave with it.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(1)
Topics
This problem involves: Linked List, Recursion.
Companies
Asked at: Adobe, Amazon, Apple, Arista Networks, Bloomberg, Capital One, Cognizant, EPAM Systems, Flipkart, Goldman Sachs, HPE, Huawei, Hubspot, Infosys, Intel, Intuit, LinkedIn, Media.net, Meta, Microsoft, Oracle, Palo Alto Networks, Revolut, Rippling, Shopee, Siemens, Snap, Snowflake, Swiggy, Teradata, Texas Instruments, TikTok, Uber, Visa, Walmart Labs, Wix, Yahoo, Yandex, tcs.