Merge Sorted Array - Complete Solution Guide
Merge Sorted Array is LeetCode problem 88, 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 two integer arrays nums1 and nums2 , sorted in non-decreasing order , and two integers m and n , representing the number of elements in nums1 and nums2 respectively. Merge nums1 and nums2 into a single array sorted in non-decreasing order . The final sorted array should not be returned by the function, but instead be stored inside the array nums1 . To accommodate this, nums1 has a length of m + n , where the first m elements denote the elements that should be merged, and the last n
Detailed Explanation
This problem asks us to merge two already sorted integer arrays, `nums1` and `nums2`, directly into `nums1` itself. The crucial setup details are what make this problem interesting: `nums1` initially contains `m` elements, representing its 'active' data, followed by `n` zero-padded spaces. This means `nums1` has a total length of `m + n`, precisely enough to hold all elements from both arrays. `nums2` contains `n` elements. Both arrays are sorted in non-decreasing order.
Solution Approach
The elegant solution to this problem leverages the fact that `nums1`'s extra space is conveniently located at its *end*, and both input arrays are sorted. Instead of attempting to merge from the beginning, which would necessitate complex shifting of `nums1`'s existing elements to make room (and potential data loss), we approach the problem by merging from the *end* of the combined array backward. We maintain three pointers: `p1` points to the last *actual* element of `nums1` (at index `m-1`), `p2` points to the last element of `nums2` (at index `n-1`), and `p` points to the last available position in `nums1` where a merged element should be placed (at index `m+n-1`). The algorithm proceeds by comparing the elements pointed to by `p1` and `p2`. Whichever element is larger (or equal) is the one that should occupy the current largest available slot `p`. We place that element at `nums1[p]`, and then decrement `p` and the pointer from which we took the element (`p1` or `p2`). This process continues as long as both `p1` and `p2` are valid (non-negative). This backward traversal is key: it ensures we are always writing into empty or already processed space, never overwriting a `nums1` element that we still need to compare. A crucial final step handles the scenario where `nums2` still has elements remaining after `nums1`'s initial `m` elements have all been placed. This happens if `nums2` contains elements that are all smaller than the remaining elements of `nums1` (or `nums1`'s elements are exhausted first). If `p1` reaches `-1` but `p2` is still valid, all remaining elements in `nums2` are simply copied directly into the remaining slots in `nums1` from `p` downwards, as they are already sorted and belong at the front of the merged array.
Step-by-Step Algorithm
- Step 1: Initialize three pointers: `p1` to `m - 1`, `p2` to `n - 1`, and `p` to `m + n - 1`. These point to the last elements of the relevant portions of the arrays.
- Step 2: Compare `nums1[p1]` and `nums2[p2]`. The larger element is placed at `nums1[p]`, and the corresponding pointer (`p1` or `p2`) is decremented. `p` is also decremented.
- Step 3: Repeat Step 2 until either `p1` or `p2` reaches the beginning of its array (i.e., `p1 < 0` or `p2 < 0`).
- Step 4: If any elements remain in `nums2` (`p2 >= 0`), copy the remaining elements from `nums2` to the beginning portion of `nums1`.
Key Insights
- **Merge from the Rear to Prevent Overwriting:** The fundamental insight is to perform the merge operation starting from the *end* of the combined logical array and working backward into `nums1`. Since the available empty space in `nums1` is at its tail (indices `m` through `m+n-1`), filling these spots with the largest elements first ensures that `nums1`'s original `m` elements are never overwritten before they've been properly compared and potentially moved.
- **Three-Pointer Simultaneous Traversal:** Employing three distinct pointers (`p1` for `nums1`'s active elements, `p2` for `nums2`'s elements, and `p` for the current write position in `nums1`) streamlines the logic. In each iteration, we compare `nums1[p1]` and `nums2[p2]`, place the larger element at `nums1[p]`, and then decrement `p` along with the pointer that contributed the element. This systematic decrement ensures all elements are considered and placed in their correct sorted position.
- **Special Handling for Remaining `nums2` Elements:** An important edge case arises if `nums1`'s `m` elements are exhausted (i.e., `p1` becomes negative) while `nums2` still has elements remaining (`p2` is non-negative). This implies all remaining `nums2` elements are smaller than any elements already placed from `nums1` and thus belong at the beginning of the merged array. A dedicated loop to copy these remaining `nums2` elements directly into `nums1` is essential. No similar loop is strictly needed for remaining `nums1` elements because they are already *in* `nums1` in their correct relative positions.
Complexity Analysis
Time Complexity: O(m+n)
Space Complexity: O(1)
Topics
This problem involves: Array, Two Pointers, Sorting.
Companies
Asked at: Accenture, Adobe, Agoda, Amazon, Apple, Atlassian, Avito, Barclays, Bloomberg, ByteDance, Canonical, Cisco, Cognizant, Criteo, EPAM Systems, Expedia, Goldman Sachs, HCL, Hubspot, IBM, Infosys, Intel, LinkedIn, Meta, Microsoft, Netflix, Nvidia, Oracle, Palo Alto Networks, PayPal, Qualcomm, ServiceNow, Squarespace, Swiggy, TikTok, Uber, VK, Virtusa, Walmart Labs, Wipro, Yahoo, Yandex, Zoho, athenahealth, persistent systems, tcs.