88. Merge Sorted Array - Explanation
Description
You are given two integer arrays nums1 and nums2, both sorted in non-decreasing order, along with two integers m and n, where:
mis the number of valid elements innums1,nis the number of elements innums2.
The array nums1 has a total length of (m+n), with the first m elements containing the values to be merged, and the last n elements set to 0 as placeholders.
Your task is to merge the two arrays such that the final merged array is also sorted in non-decreasing order and stored entirely within nums1.
You must modify nums1 in-place and do not return anything from the function.
Example 1:
Input: nums1 = [10,20,20,40,0,0], m = 4, nums2 = [1,2], n = 2
Output: [1,2,10,20,20,40]Example 2:
Input: nums1 = [0,0], m = 0, nums2 = [1,2], n = 2
Output: [1,2]Constraints:
0 <= m, n <= 2001 <= (m + n) <= 200nums1.length == (m + n)nums2.length == n-1,000,000,000 <= nums1[i], nums2[i] <= 1,000,000,000
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Arrays - Understanding how to access and modify elements by index
- Two Pointers - Traversing arrays from different directions simultaneously
- In-place Algorithms - Modifying data structures without using extra space
1. Sorting
Intuition
The simplest approach is to copy all elements from nums2 into the empty slots at the end of nums1, then sort the entire array. Since nums1 has enough space allocated for both arrays, we can place nums2's elements starting at index m. After sorting, the merged result is in sorted order.
Algorithm
- Copy all
nelements fromnums2intonums1starting at indexm. - Sort
nums1in place.
Time & Space Complexity
- Time complexity:
- Space complexity: or depending on the sorting algorithm.
Where and represent the number of elements in the arrays and , respectively.
2. Three Pointers With Extra Space
Intuition
Since both arrays are already sorted, we can merge them in linear time using the standard merge technique from merge sort. However, if we write directly into nums1 from the front, we risk overwriting elements we still need. To avoid this, we first copy the original elements of nums1 to a temporary array, then merge from both sources into nums1.
Algorithm
- Create a copy of the first
melements ofnums1. - Use three pointers:
ifor the copy ofnums1,jfornums2, andidxfor the write position innums1. - Compare elements from both sources and write the smaller one to
nums1[idx]. - Increment the corresponding pointer and
idx. - Continue until all elements from both sources are placed.
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
nums1_copy = nums1[:m]
idx = 0
i = j = 0
while idx < m + n:
if j >= n or (i < m and nums1_copy[i] <= nums2[j]):
nums1[idx] = nums1_copy[i]
i += 1
else:
nums1[idx] = nums2[j]
j += 1
idx += 1Time & Space Complexity
- Time complexity:
- Space complexity:
Where and represent the number of elements in the arrays and , respectively.
3. Three Pointers Without Extra Space - I
Intuition
The key insight is that nums1 has empty space at the end. If we fill from the back instead of the front, we never overwrite elements we still need. By comparing the largest remaining elements from both arrays and placing the larger one at the current end position, we can merge in place without extra space.
Algorithm
- Initialize
lasttom + n - 1(the last index ofnums1). - While both
m > 0andn > 0:- Compare
nums1[m - 1]andnums2[n - 1]. - Place the larger value at
nums1[last]and decrement the corresponding pointer. - Decrement
last.
- Compare
- If any elements remain in
nums2, copy them tonums1.
class Solution:
def merge(self, nums1: list[int], m: int, nums2: list[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
last = m + n - 1
# Merge in reverse order
while m > 0 and n > 0:
if nums1[m - 1] > nums2[n - 1]:
nums1[last] = nums1[m - 1]
m -= 1
else:
nums1[last] = nums2[n - 1]
n -= 1
last -= 1
# Fill nums1 with leftover nums2 elements
while n > 0:
nums1[last] = nums2[n - 1]
n -= 1
last -= 1Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
Where and represent the number of elements in the arrays and , respectively.
4. Three Pointers Without Extra Space - II
Intuition
This is a cleaner version of the previous approach. We observe that once all elements from nums2 are placed, the remaining elements of nums1 are already in their correct positions. So we only need to loop while j >= 0. This simplifies the logic and removes the need for a separate cleanup loop.
Algorithm
- Initialize pointers
i = m - 1,j = n - 1, andlast = m + n - 1. - While
j >= 0:- If
i >= 0andnums1[i] > nums2[j], placenums1[i]atnums1[last]and decrementi. - Otherwise, place
nums2[j]atnums1[last]and decrementj. - Decrement
last.
- If
class Solution:
def merge(self, nums1: list[int], m: int, nums2: list[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
last = m + n - 1
i, j = m - 1, n - 1
while j >= 0:
if i >= 0 and nums1[i] > nums2[j]:
nums1[last] = nums1[i]
i -= 1
else:
nums1[last] = nums2[j]
j -= 1
last -= 1Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
Where and represent the number of elements in the arrays and , respectively.
Common Pitfalls
Merging From the Front Instead of the Back
When merging in place, starting from the front of nums1 overwrites elements that have not yet been processed. This destroys data you still need. Always merge from the back of nums1 where there is empty space, placing the largest elements first.
Forgetting to Copy Remaining Elements From nums2
After the main merge loop, if there are remaining elements in nums2, they must be copied to nums1. Elements remaining in nums1 are already in their correct positions, but leftover nums2 elements need explicit placement. Missing this step leaves the result incomplete.
Sign in to join the discussion