0088 - Merge Sorted Array (Easy)
Problem Link
https://leetcode.com/problems/merge-sorted-array/
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 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 + nnums2.length == n0 <= m, n <= 2001 <= m + n <= 200-10^9 <= nums1[i], nums2[j] <= 10^9
Follow up: Can you come up with an algorithm that runs in O(m + n) time?
Approach 1: Brute Force
Since, this problem is under easy category, we know has length so we add the elements of in the empty spaces of . Finally, we sort the with any standard sorting algorithm. This solution gives time complexity and space complexity.
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
// adding elements of nums2 at empty places of nums1
// starting at index m
for(int i = 0; i < n; i++) {
nums1[m + i] = nums2[i];
}
// sorting nums1 in an ascending order
Arrays.sort(nums1);
}
}Approach 2: Two Pointers
A better way to do it is using one-pass two pointer approach. We make a copy of into , then iterate through both arrays and comparing their elements in ascending fashion with the help of two pointers and ,simultaneouslty adding the smaller elements into . Finally, the bigger elements out of either or are going to be added by seperately iterating over them if or satisfies the conditions. This solution gives or time complexity and or space complexity.
class Solution {
public void merge(int[] nums1 , int m , int[] nums2 , int n) {
int i = 0, j = 0, k = 0;
// making a temp copy of nums1, for easier swapping of elements
int[] temp = Arrays.copyOfRange(nums1 , 0 , m);
// loop till anyone array elements exhausts
while (i < m && j < n) {
// adding the elements into nums1 in ascending order
if (temp[i] < nums2[j]) {
nums1[k] = temp[i];
i++;
} else {
nums1[k] = nums2[j];
j++;
}
k++;
}
// now adding the left out elements either of temp or nums2
// Either one of the loops will execute because every time one array's length
// would come out to be shorter than the other one
while (i < m) {
nums1[k] = temp[i];
k++;
i++;
}
while (j < n) {
nums1[k] = nums2[j];
k++;
j++;
}
}
}Approach 3: Two Pointers In-place (Optimal)
As we know, can hold size of array, which can have empty slots at the end to move array.
Since the array is already sorted, we can place the elements from highest to lowest in by moving from last slot to first.
Time Complexity: , where, - length of nums1, - length of nums2
Space complexity:
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
// index position for array placements
int idx = nums1.length - 1; m -= 1; n -= 1;
while (n >= 0) {
// Place elements from right direction to left.
if (m >= 0 && nums1[m] > nums2[n]) {
nums1[idx] = nums1[m--];
} else {
nums1[idx] = nums2[n--];
}
idx--;
}
}
}Approach 4: Shell sort
-
Calculate the gap value for merging the two arrays. The gap is determined as .
-
Initialize two pointers: the left pointer at index and the right pointer at index (left + gap).
-
Perform the following steps for each gap until the gap becomes :
- Inside a loop that continues until the right pointer reaches the end (i.e., index ), handle three different cases:
- If the left pointer is inside and the right pointer is in , compare and . If , swap them.
- If both pointers are in , compare and . If , swap them.
- If both pointers are in , compare and . If , swap them.
- Inside a loop that continues until the right pointer reaches the end (i.e., index ), handle three different cases:
-
After the right pointer reaches the end, decrease the value of the gap by setting it to .
-
Repeat the loop until the gap becomes .
-
Finally, after performing all the operations, you will have the merged sorted array.
class Solution {
public:
void swapIfGreater(vector<int>& arr1, vector<int>& arr2, int ind1, int ind2) {
if (arr1[ind1] > arr2[ind2]) {
swap(arr1[ind1], arr2[ind2]);
}
}
void merge(vector<int>& arr1, int n, vector<int>& arr2, int m) {
int len = n + m;
// initial gap:
int gap = (len / 2) + (len % 2);
while (gap > 0) {
// place 2 pointers:
int left = 0, right = left + gap;
while (right < len) {
// case 1: left in arr1 and right in arr2:
if (left < n && right >= n) swapIfGreater(arr1, arr2, left, right - n);
// case 2: both pointers in arr2:
else if (left >= n) swapIfGreater(arr2, arr2, left - n, right - n);
// case 3: both pointers in arr1:
else swapIfGreater(arr1, arr1, left, right);
left++, right++;
}
// break if iteration gap=1 is completed:
if (gap == 1) break;
// otherwise, calculate new gap:
gap = (gap / 2) + (gap % 2);
}
int j = 0;
for (int i = n; i < n + m; i++) {
arr1[i] = arr2[j];
j++;
}
}
};