RezloRezloPrep
On this page

Merge Sorted Array

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 nums2 into nums1 so that nums1 becomes a single array sorted in non-decreasing order.

The result must be stored inside nums1. To make room, nums1 has a length of m + n. The first m elements are the real values, and the last n elements are 0 and should be ignored.

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

Brute Force

A straightforward approach is to ignore the fact that both arrays are already sorted.

  1. Copy every element of nums2 into the empty slots at the end of nums1.
  2. Sort nums1.

This works, but sorting does not take advantage of the existing order of the two arrays.

Time: O((m + n) log(m + n))

Space: O(log(m + n)) for the sorting algorithm's stack (or O(m + n) if you merge using a separate helper array)

We can improve this by merging the arrays directly, without sorting and without extra memory.

Optimal Approach: Three Pointers From the End

If we merge from the front, we would overwrite elements of nums1 that have not been processed yet.

The key observation is that the end of nums1 is empty. So we fill nums1 from the back, placing the largest elements first.

Use three pointers:

  • i at the last real element of nums1 (index m - 1).
  • j at the last element of nums2 (index n - 1).
  • k at the last position of nums1 (index m + n - 1).

At each step, compare nums1[i] and nums2[j].

Place the larger one at nums1[k], then move that pointer and k one step left.

When nums2 is fully placed, we are done. Any remaining elements in nums1 are already in the correct position.

Code Solutions

class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1;
int j = n - 1;
int k = m + n - 1;
while (j >= 0) {
if (i >= 0 && nums1[i] > nums2[j]) {
nums1[k] = nums1[i];
i--;
} else {
nums1[k] = nums2[j];
j--;
}
k--;
}
}
};

Why Do We Loop Only While j >= 0?

There are two ways the loop can finish.

If nums2 runs out first, the remaining elements of nums1 are already sorted and already in their final positions. Nothing needs to move.

If nums1 runs out first (i < 0), the condition i >= 0 && ... fails, so the remaining nums2 elements are copied into the front of nums1.

So the only thing that must be finished is nums2.

Why This Is Better Than Brute Force

The brute-force approach re-sorts everything, even though both arrays are already sorted.

The three-pointer approach uses that existing order. Each step places exactly one element in its final position, so every element is touched only once.

This reduces the solution from O((m + n) log(m + n)) to O(m + n) time.

Complexity

Time: O(m + n)

Each iteration places one element into its final position. There are at most m + n positions to fill.

Space: O(1)

The merge happens in place inside nums1. We only use three integer pointers.

How to Explain It in an Interview

How to Explain it in an Interview

The 30-Second Spoken Pitch
"Since both arrays are sorted and nums1 has empty space at the end, I merge from the back instead of the front. I keep one pointer at the last real element of nums1, one at the last element of nums2, and one at the last index of nums1. At each step I compare the two elements, write the larger one at the write pointer, and move the pointers left. Filling from the back means I never overwrite an element I still need. I loop until nums2 is fully placed, because if nums1 has leftovers, they are already in the correct place. The time complexity is O(m + n) and the extra space is O(1)."
Next TopicRemove Element