🧠
Optimal Approach (Two Pointers Backwards In-Place)
💡 This is the optimal solution that merges nums2 into nums1 in-place by using two pointers starting from the end. It avoids extra space and overwriting issues by filling nums1 from the back.
Intuition
Since nums1 has extra space at the end, start merging from the largest elements at the end to avoid overwriting unmerged elements.
Algorithm
- Initialize three pointers: i at m-1 (end of valid nums1), j at n-1 (end of nums2), and k at m+n-1 (end of nums1).
- Compare nums1[i] and nums2[j]. Place the larger at nums1[k].
- Move the pointer (i or j) of the placed element and decrement k.
- If nums2 still has elements left, copy them into nums1.
- No need to copy remaining nums1 elements as they are already in place.
💡 This algorithm cleverly uses the extra space at the end of nums1 and merges backwards to avoid overwriting.
def merge(nums1, m, nums2, n):
i = m - 1
j = n - 1
k = m + n - 1
while i >= 0 and j >= 0:
if nums1[i] > nums2[j]:
nums1[k] = nums1[i]
i -= 1
else:
nums1[k] = nums2[j]
j -= 1
k -= 1
while j >= 0:
nums1[k] = nums2[j]
j -= 1
k -= 1
# Driver code
if __name__ == "__main__":
nums1 = [1,2,3,0,0,0]
m = 3
nums2 = [2,5,6]
n = 3
merge(nums1, m, nums2, n)
print(nums1)
Line Notes
i = m - 1Pointer to last valid element in nums1
j = n - 1Pointer to last element in nums2
while i >= 0 and j >= 0:Loop until one array is fully merged
nums1[k] = nums1[i]Place larger element at the end to avoid overwriting
import java.util.Arrays;
public class Solution {
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) nums1[k--] = nums1[i--];
else nums1[k--] = nums2[j--];
}
while (j >= 0) nums1[k--] = nums2[j--];
}
public static void main(String[] args) {
int[] nums1 = {1,2,3,0,0,0};
int m = 3;
int[] nums2 = {2,5,6};
int n = 3;
merge(nums1, m, nums2, n);
System.out.println(Arrays.toString(nums1));
}
}
Line Notes
int i = m - 1, j = n - 1, k = m + n - 1;Initialize pointers at the end of valid elements and total array
while (i >= 0 && j >= 0)Merge until one array is exhausted
nums1[k--] = nums1[i--];Place larger element from nums1 at the end
while (j >= 0) nums1[k--] = nums2[j--];Copy remaining nums2 elements if any
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) nums1[k--] = nums1[i--];
else nums1[k--] = nums2[j--];
}
while (j >= 0) nums1[k--] = nums2[j--];
}
int main() {
vector<int> nums1 = {1,2,3,0,0,0};
int m = 3;
vector<int> nums2 = {2,5,6};
int n = 3;
merge(nums1, m, nums2, n);
for (int x : nums1) cout << x << " ";
cout << endl;
return 0;
}
Line Notes
int i = m - 1, j = n - 1, k = m + n - 1;Pointers start from the end of valid elements and total array
while (i >= 0 && j >= 0)Merge elements from the back until one array is exhausted
nums1[k--] = nums1[i--];Place larger element from nums1 at the end
while (j >= 0) nums1[k--] = nums2[j--];Copy leftover nums2 elements if any
function merge(nums1, m, nums2, n) {
let i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k--] = nums1[i--];
} else {
nums1[k--] = nums2[j--];
}
}
while (j >= 0) {
nums1[k--] = nums2[j--];
}
}
// Driver code
let nums1 = [1,2,3,0,0,0];
let m = 3;
let nums2 = [2,5,6];
let n = 3;
merge(nums1, m, nums2, n);
console.log(nums1);
Line Notes
let i = m - 1, j = n - 1, k = m + n - 1;Initialize pointers at the end of valid elements and total array
while (i >= 0 && j >= 0)Merge elements from the back until one array is exhausted
nums1[k--] = nums1[i--];Place larger element from nums1 at the end
while (j >= 0) { nums1[k--] = nums2[j--]; }Copy remaining nums2 elements if any
We traverse both arrays once and merge in-place without extra space.
💡 For n=1000, this means about 2000 operations and no extra memory, which is optimal.
Interview Verdict: Accepted and optimal
This is the best approach to implement in interviews as it uses the sorted property and extra space efficiently.