88. Merge Sorted Array
Description
Difficulty: Easy
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
elements are set to 0
and should be ignored. nums2
has a length of n
.
Example 1:
Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
The result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.
Example 2:
Input: nums1 = [1], m = 1, nums2 = [], n = 0
Output: [1]
Explanation: The arrays we are merging are [1] and [].
The result of the merge is [1].
Example 3:
Input: nums1 = [0], m = 0, nums2 = [1], n = 1
Output: [1]
Explanation: The arrays we are merging are [] and [1].
The result of the merge is [1].
Note that because m = 0, there are no elements in nums1. The 0 is only there to ensure the merge result can fit in nums1.
Constraints:
- nums1.length == m + n
- nums2.length == n
- 0 <= m, n <= 200
- 1 <= m + n <= 200
- -109 <= nums1[i], nums2[j] <= 109
Follow up: Can you come up with an algorithm that runs in O(m + n)
time?
Solution
A key constraint is that nums1
has enough space to accommodate all elements from both arrays (specifically, its initial size is m + n
, where m
is the number of actual elements in nums1
and n
is the number of elements in nums2
). The operation is performed in-place, directly modifying nums1
without using additional auxiliary arrays for the primary merge logic.
The strategy employs a three-pointer approach, working from the end of the arrays towards the beginning to avoid overwriting elements in nums1
that have not yet been moved.
Pointer Initialization:
p1
: Initialized tom - 1
, pointing to the last valid element innums1
(before any elements fromnums2
are considered).p2
: Initialized ton - 1
, pointing to the last element innums2
.p
: Initialized tom + n - 1
, pointing to the last available position innums1
where merged elements will be placed.
Main Merge Loop (
while (p1 >= 0 && p2 >= 0)
): This loop continues as long as there are elements remaining in bothnums1
(original part) andnums2
to compare.Comparison: At each step, the elements
nums1[p1]
andnums2[p2]
are compared.Placement:
If
nums1[p1]
is greater than or equal tonums2[p2]
, it signifies thatnums1[p1]
is the largest among the currently considered elements. Thus,nums1[p1]
is moved tonums1[p]
.p1
is then decremented to consider the next smaller element innums1
.Otherwise (if
nums2[p2]
is larger),nums2[p2]
is moved tonums1[p]
.p2
is then decremented to consider the next smaller element innums2
.
Destination Pointer Decrement: In either case,
p
is decremented as an element has been placed in its final sorted position innums1
.
Handling Remaining Elements (
while (p2 >= 0)
): After the main loop finishes, it's possible that elements fromnums2
still remain (if all elements fromnums1
were smaller and exhausted first).- This loop copies any remaining elements from
nums2
directly into the beginning ofnums1
(which would be the available slots pointed to byp
). Bothp2
andp
are decremented in each iteration until all elements fromnums2
are moved. (Note: No similar loop is needed fornums1
because its remaining elements would already be in their correct sorted positions at the beginning ofnums1
ifp2
became -1 first.)
- This loop copies any remaining elements from
Code
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = m - 1;
int p2 = n - 1;
int p = m + n - 1;
while (p1 >= 0 && p2 >= 0) {
if (nums1[p1] >= nums2[p2]) {
nums1[p] = nums1[p1];
--p1;
} else {
nums1[p] = nums2[p2];
--p2;
}
--p;
}
while (p2 >= 0) {
nums1[p] = nums2[p2];
--p2;
--p;
}
}
}
Time Complexity: O(m + n)
The algorithm performs a single pass, in reverse, through both arrays. In the worst case, each element from nums1
(m elements) and nums2
(n elements) is visited and moved exactly once. Therefore, the number of operations is directly proportional to the total number of elements being merged.
Space Complexity: O(1)
The algorithm operates entirely in-place, modifying nums1
directly. It uses only a few constant-space pointers (p1
, p2
, p
), regardless of the input array sizes. No auxiliary data structures that scale with m
or n
are allocated.