Merge Two Sorted Arrays Without Extra Space (original) (raw)
Given two sorted arrays **a[] and b[] of size **n and m respectively, merge both the arrays and rearrange the elements such that the smallest **n elements are in **a[] and the remaining **m elements are in **b[]. All elements in a[] and b[] should be in sorted order.
**Examples:
**Input: a[] = [2, 4, 7, 10], b[] = [2, 3]
**Output: a[] = [2, 2, 3, 4], b[] = [7, 10]
**Explanation: Combined sorted array = [2, 2, 3, 4, 7, 10], array a[] contains smallest 4 elements: 2, 2, 3 and 4, and array b[] contains remaining 2 elements: 7, 10.**Input: a[] = [1, 5, 9, 10, 15, 20], b[] = [2, 3, 8, 13]
**Output: a[] = [1, 2, 3, 5, 8, 9], b[] = [10, 13, 15, 20]
**Explanation: Combined sorted array = [1, 2, 3, 5, 8, 9, 10, 13, 15, 20], array a[] contains smallest 6 elements: 1, 2, 3, 5, 8 and 9, and array b[] contains remaining 4 elements: 10, 13, 15, 20.**Input: a[] = [0, 1], b[] = [2, 3]
**Output: a[] = [0, 1], b[] = [2, 3]
**Explanation: Combined sorted array = [0, 1, 2, 3], array a[] contains smallest 2 elements: 0 and 1, and array b[] contains remaining 2 elements: 2 and 3.
Table of Content
**[Naive Approach] Using Insert of Insertion Sort
The idea is to traverse **b[] from the **end in reverse order and compare each element with the last (largest) element of **a[]. For any index **i, if **b[i] is smaller than the last element of a[], replace **b[i] with the last element of a[] and use insert step of insertion sort to find the correct place of **b[i] in a[].
**How do we keep a[] sorted? Every time we add any element from **b[] to **a[], we find the correct index using insert step of insertion sort.
**How do we keep b[] sorted? This is ensured by the fact that we traverse **b[] from end and insert only when current element of **b[] is smaller.
**Illustration

C++ `
#include #include using namespace std;
void mergeArrays(vector& a, vector& b) {
// Traverse b[] starting from the last element
for (int i = b.size() - 1; i >= 0; i--) {
// If b[i] is smaller than the largest element of a[]
if (a.back() > b[i]) {
// Place b[i] in the correct position in a[],
// and move last element of a[] to b[]
int last = a.back();
int j = a.size() - 2;
while (j >= 0 && a[j] > b[i]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = b[i];
b[i] = last;
}
}}
int main() { vector a = {1, 5, 9, 10, 15, 20}; vector b = {2, 3, 8, 13}; mergeArrays(a, b);
for (int ele: a)
cout << ele << " ";
cout << "\n";
for (int ele: b)
cout << ele << " ";
return 0;}
C
#include <stdio.h>
void mergeArrays(int a[], int b[], int n, int m) {
// Traverse b[] starting from the last element
for (int i = m - 1; i >= 0; i--) {
// If b[i] is smaller than the largest element of a[]
if (a[n - 1] > b[i]) {
// Place b[i] in the correct position in a[],
// and move last element of a[] to b[]
int last = a[n - 1];
int j = n - 2;
while (j >= 0 && a[j] > b[i]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = b[i];
b[i] = last;
}
}}
int main() { int a[] = {1, 5, 9, 10, 15, 20}; int b[] = {2, 3, 8, 13}; int n = sizeof(a) / sizeof(a[0]); int m = sizeof(b) / sizeof(b[0]);
mergeArrays(a, b, n, m);
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
for (int i = 0; i < m; i++)
printf("%d ", b[i]);
return 0;}
Java
import java.util.Arrays;
class GfG {
static void mergeArrays(int[] a, int[] b) {
// Traverse b[] starting from the last element
for (int i = b.length - 1; i >= 0; i--) {
// If b[i] is smaller than the largest element of a[]
if (a[a.length - 1] > b[i]) {
// Place b[i] in the correct position in a[],
// and move last element of a[] to b[]
int last = a[a.length - 1];
int j = a.length - 2;
while (j >= 0 && a[j] > b[i]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = b[i];
b[i] = last;
}
}
}
public static void main(String[] args) {
int[] a = {1, 5, 9, 10, 15, 20};
int[] b = {2, 3, 8, 13};
mergeArrays(a, b);
for (int ele : a)
System.out.print(ele + " ");
System.out.println();
for (int ele : b)
System.out.print(ele + " ");
}}
Python
def mergeArrays(a, b):
# Traverse b[] starting from the last element
for i in range(len(b) - 1, -1, -1):
# If b[i] is smaller than the largest element of a[]
if a[-1] > b[i]:
# Place b[i] in the correct position in a[],
# and move last element of a[] to b[]
last = a[-1]
j = len(a) - 2
while j >= 0 and a[j] > b[i]:
a[j + 1] = a[j]
j -= 1
a[j + 1] = b[i]
b[i] = lastif name == "main": a = [1, 5, 9, 10, 15, 20] b = [2, 3, 8, 13] mergeArrays(a, b)
for ele in a:
print(ele, end=" ")
print();
for ele in b:
print(ele, end=" ")C#
using System;
class GfG { static void mergeArrays(int[] a, int[] b) {
// Traverse b[] starting from the last element
for (int i = b.Length - 1; i >= 0; i--) {
// If b[i] is smaller than the largest element of a[]
if (a[a.Length - 1] > b[i]) {
// Place b[i] in the correct position in a[],
// and move last element of a[] to b[]
int last = a[a.Length - 1];
int j = a.Length - 2;
while (j >= 0 && a[j] > b[i]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = b[i];
b[i] = last;
}
}
}
static void Main() {
int[] a = { 1, 5, 9, 10, 15, 20 };
int[] b = { 2, 3, 8, 13 };
mergeArrays(a, b);
foreach (int ele in a)
Console.Write(ele + " ");
Console.WriteLine();
foreach (int ele in b)
Console.Write(ele + " ");
}}
JavaScript
function mergeArrays(a, b) {
// Traverse b[] starting from the last element
for (let i = b.length - 1; i >= 0; i--) {
// If b[i] is smaller than the largest element of a[]
if (a[a.length - 1] > b[i]) {
// Place b[i] in the correct position in a[],
// and move last element of a[] to b[]
let last = a[a.length - 1];
let j = a.length - 2;
while (j >= 0 && a[j] > b[i]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = b[i];
b[i] = last;
}
}}
// Driver Code const a = [1, 5, 9, 10, 15, 20]; const b = [2, 3, 8, 13]; mergeArrays(a, b);
console.log(a.join(" ")); console.log(b.join(" "));
`
Output
1 2 3 5 8 9 10 13 15 20
**Time Complexity: O(m * n), where **n and **m are sizes of **a[] and **b[] respectively.
**Auxiliary Space: O(1)
[Better Approach 1] Using n-th smallest element
We can use the fact that **nth smallest element in the sorted combined array acts as a **pivot dividing the elements among **a[] and **b[]. Initially, this nth smallest element can lie in either arrays so instead of finding it, we can find the first index **idx in **a[], such that the elements after this index were larger than the **pivot.
Elements of a[] placed after index **idx should be replaced with smaller elements from **b[]. Now all elements were in the correct arrays and we can apply sorting to both arrays to maintain the order.
C++ `
#include #include #include <limits.h> #include using namespace std;
// Find m-th smallest element // Do a binary search in a[] to find the right index idx // in a[] such that all combined elements in a[idx..m-1] // and b[m-idx...n-1] are greater than or equal to all // the remaining elements (a[0..idx-1] and b[m-idx-1..n-1]) // in both the arrays. int kthSmallest(vector &a, vector &b, int k) { int n = a.size(), m = b.size(); int lo = 0, hi = n, idx = 0; while (lo <= hi) { int mid1 = (lo + hi) / 2; int mid2 = k - mid1;
// We don't have mid2 elements in b[], so pick more
// elements from a[]
if (mid2 > m) {
lo = mid1 + 1;
continue;
}
// Find elements to the left and right of partition in a[]
int l1 = (mid1 == 0 ? INT_MIN : a[mid1 - 1]);
int r1 = (mid1 == n ? INT_MAX : a[mid1]);
// Find elements to the left and right of partition in b[]
int l2 = (mid2 == 0 ? INT_MIN : b[mid2 - 1]);
int r2 = (mid2 == m ? INT_MAX : b[mid2]);
// If it is a valid partition
if (l1 <= r2 && l2 <= r1) {
idx = mid1;
break;
}
// Check if we need to take lesser elements from a[]
if (l1 > r2)
hi = mid1 - 1;
// Check if we need to take more elements from a[]
else
lo = mid1 + 1;
}
return idx;}
void mergeArrays(vector &a, vector &b) { int n = a.size(); int m = b.size(); int idx = kthSmallest(a, b, n);
// Move all smaller elements in a[]
for (int i = idx; i < n; i++) {
swap(a[i], b[i - idx]);
}
// Sort both a[] and b[]
sort(a.begin(), a.end());
sort(b.begin(), b.end());}
int main() { vector a = {1, 5, 9, 10, 15, 20}; vector b = {2, 3, 8, 13}; mergeArrays(a, b);
for (int ele : a)
cout << ele << " ";
cout << "\n";
for (int ele : b)
cout << ele << " ";
return 0;}
C
#include <stdio.h> #include <limits.h>
int compare(const void *a, const void b) { return ((int *)a - *(int *)b); }
// Find m-th smallest element // Do a binary search in a[] to find the right index idx // in a[] such that all combined elements in a[idx..m-1] // and b[m-idx...n-1] are greater than or equal to all // the remaining elements (a[0..idx-1] and b[m-idx-1..n-1]) // in both the arrays. int kthSmallest(int *a, int n, int *b, int m, int k) { int lo = 0, hi = n, idx = 0; while (lo <= hi) { int mid1 = (lo + hi) / 2; int mid2 = k - mid1;
// We don't have mid2 elements in b[], so pick more
// elements from a[]
if (mid2 > m) {
lo = mid1 + 1;
continue;
}
// Find elements to the left and right of partition in a[]
int l1 = (mid1 == 0 ? INT_MIN : a[mid1 - 1]);
int r1 = (mid1 == n ? INT_MAX : a[mid1]);
// Find elements to the left and right of partition in b[]
int l2 = (mid2 == 0 ? INT_MIN : b[mid2 - 1]);
int r2 = (mid2 == m ? INT_MAX : b[mid2]);
// If it is a valid partition
if (l1 <= r2 && l2 <= r1) {
idx = mid1;
break;
}
// Check if we need to take lesser elements from a[]
if (l1 > r2)
hi = mid1 - 1;
// Check if we need to take more elements from a[]
else
lo = mid1 + 1;
}
return idx;}
void mergeArrays(int *a, int n, int *b, int m) { int idx = kthSmallest(a, n, b, m, n);
// Move all smaller elements in a[]
for (int i = idx; i < n; i++) {
int temp = a[i];
a[i] = b[i - idx];
b[i - idx] = temp;
}
// Sort both a[] and b[]
qsort(a, n, sizeof(int), compare);
qsort(b, m, sizeof(int), compare);}
int main() { int a[] = {1, 5, 9, 10, 15, 20}; int b[] = {2, 3, 8, 13}; int n = sizeof(a) / sizeof(a[0]); int m = sizeof(b) / sizeof(b[0]); mergeArrays(a, n, b, m);
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
for (int i = 0; i < m; i++)
printf("%d ", b[i]);
return 0;}
Java
import java.util.Arrays;
class GfG {
// Find m-th smallest element
// Do a binary search in a[] to find the right index idx
// in a[] such that all combined elements in a[idx..m-1]
// and b[m-idx...n-1] are greater than or equal to all
// the remaining elements (a[0..idx-1] and b[m-idx-1..n-1])
// in both the arrays.
static int kthSmallest(int[] a, int[] b, int k) {
int n = a.length, m = b.length;
int lo = 0, hi = n, idx = 0;
while (lo <= hi) {
int mid1 = (lo + hi) / 2;
int mid2 = k - mid1;
// We don't have mid2 elements in b[], so pick more
// elements from a[]
if (mid2 > m) {
lo = mid1 + 1;
continue;
}
// Find elements to the left and right of partition in a[]
int l1 = (mid1 == 0 ? Integer.MIN_VALUE : a[mid1 - 1]);
int r1 = (mid1 == n ? Integer.MAX_VALUE : a[mid1]);
// Find elements to the left and right of partition in b[]
int l2 = (mid2 == 0 ? Integer.MIN_VALUE : b[mid2 - 1]);
int r2 = (mid2 == m ? Integer.MAX_VALUE : b[mid2]);
// If it is a valid partition
if (l1 <= r2 && l2 <= r1) {
idx = mid1;
break;
}
// Check if we need to take lesser elements from a[]
if (l1 > r2)
hi = mid1 - 1;
// Check if we need to take more elements from a[]
else
lo = mid1 + 1;
}
return idx;
}
static void mergeArrays(int[] a, int[] b) {
int n = a.length;
int m = b.length;
int idx = kthSmallest(a, b, n);
// Move all smaller elements in a[]
for (int i = idx; i < n; i++) {
int temp = a[i];
a[i] = b[i - idx];
b[i - idx] = temp;
}
// Sort both a[] and b[]
Arrays.sort(a);
Arrays.sort(b);
}
public static void main(String[] args) {
int[] a = {1, 5, 9, 10, 15, 20};
int[] b = {2, 3, 8, 13};
mergeArrays(a, b);
for (int ele : a)
System.out.print(ele + " ");
System.out.println();
for (int ele : b)
System.out.print(ele + " ");
}}
Python
Find m-th smallest element
Do a binary search in a[] to find the right index idx
in a[] such that all combined elements in a[idx..m-1]
and b[m-idx...n-1] are greater than or equal to all
the remaining elements (a[0..idx-1] and b[m-idx-1..n-1])
in both the arrays.
def kthSmallest(a, b, k): n = len(a) m = len(b) lo = 0 hi = n idx = 0
while lo <= hi:
mid1 = (lo + hi) // 2
mid2 = k - mid1
# We don't have mid2 elements in b[], so pick more
# elements from a[]
if mid2 > m:
lo = mid1 + 1
continue
# Find elements to the left and right of partition in a[]
l1 = a[mid1 - 1] if mid1 > 0 else float('-inf')
r1 = a[mid1] if mid1 < n else float('inf')
# Find elements to the left and right of partition in b[]
l2 = b[mid2 - 1] if mid2 > 0 else float('-inf')
r2 = b[mid2] if mid2 < m else float('inf')
# If it is a valid partition
if l1 <= r2 and l2 <= r1:
idx = mid1
break
# Check if we need to take lesser elements from a[]
if l1 > r2:
hi = mid1 - 1
# Check if we need to take more elements from a[]
else:
lo = mid1 + 1
return idxdef mergeArrays(a, b): n = len(a) m = len(b) idx = kthSmallest(a, b, n)
# Move all smaller elements in a[]
for i in range(idx, n):
a[i], b[i - idx] = b[i - idx], a[i]
# Sort both a[] and b[]
a.sort()
b.sort()if name == "main": a = [1, 5, 9, 10, 15, 20] b = [2, 3, 8, 13] mergeArrays(a, b)
for ele in a:
print(ele, end=" ")
print()
for ele in b:
print(ele, end=" ")C#
using System;
class GfG {
// Find m-th smallest element
// Do a binary search in a[] to find the right index idx
// in a[] such that all combined elements in a[idx..m-1]
// and b[m-idx...n-1] are greater than or equal to all
// the remaining elements (a[0..idx-1] and b[m-idx-1..n-1])
// in both the arrays.
static int kthSmallest(int[] a, int[] b, int k) {
int n = a.Length, m = b.Length;
int lo = 0, hi = n, idx = 0;
while (lo <= hi) {
int mid1 = (lo + hi) / 2;
int mid2 = k - mid1;
// We don't have mid2 elements in b[], so pick more
// elements from a[]
if (mid2 > m) {
lo = mid1 + 1;
continue;
}
// Find elements to the left and right of partition in a[]
int l1 = (mid1 == 0 ? int.MinValue : a[mid1 - 1]);
int r1 = (mid1 == n ? int.MaxValue : a[mid1]);
// Find elements to the left and right of partition in b[]
int l2 = (mid2 == 0 ? int.MinValue : b[mid2 - 1]);
int r2 = (mid2 == m ? int.MaxValue : b[mid2]);
// If it is a valid partition
if (l1 <= r2 && l2 <= r1) {
idx = mid1;
break;
}
// Check if we need to take lesser elements from a[]
if (l1 > r2)
hi = mid1 - 1;
// Check if we need to take more elements from a[]
else
lo = mid1 + 1;
}
return idx;
}
static void mergeArrays(int[] a, int[] b) {
int n = a.Length;
int m = b.Length;
int idx = kthSmallest(a, b, n);
// Move all smaller elements in a[]
for (int i = idx; i < n; i++) {
int temp = a[i];
a[i] = b[i - idx];
b[i - idx] = temp;
}
// Sort both a[] and b[]
Array.Sort(a);
Array.Sort(b);
}
static void Main() {
int[] a = { 1, 5, 9, 10, 15, 20 };
int[] b = { 2, 3, 8, 13 };
mergeArrays(a, b);
foreach (int ele in a)
Console.Write(ele + " ");
Console.WriteLine();
foreach (int ele in b)
Console.Write(ele + " ");
}}
JavaScript
// Find m-th smallest element // Do a binary search in a[] to find the right index idx // in a[] such that all combined elements in a[idx..m-1] // and b[m-idx...n-1] are greater than or equal to all // the remaining elements (a[0..idx-1] and b[m-idx-1..n-1]) // in both the arrays. function kthSmallest(a, b, k) { const n = a.length, m = b.length; let lo = 0, hi = n, idx = 0;
while (lo <= hi) {
const mid1 = Math.floor((lo + hi) / 2);
const mid2 = k - mid1;
// We don't have mid2 elements in b[], so pick more
// elements from a[]
if (mid2 > m) {
lo = mid1 + 1;
continue;
}
// Find elements to the left and right of partition in a[]
const l1 = (mid1 === 0 ? Number.NEGATIVE_INFINITY : a[mid1 - 1]);
const r1 = (mid1 === n ? Number.POSITIVE_INFINITY : a[mid1]);
// Find elements to the left and right of partition in b[]
const l2 = (mid2 === 0 ? Number.NEGATIVE_INFINITY : b[mid2 - 1]);
const r2 = (mid2 === m ? Number.POSITIVE_INFINITY : b[mid2]);
// If it is a valid partition
if (l1 <= r2 && l2 <= r1) {
idx = mid1;
break;
}
// Check if we need to take lesser elements from a[]
if (l1 > r2) {
hi = mid1 - 1;
}
// Check if we need to take more elements from a[]
else {
lo = mid1 + 1;
}
}
return idx;}
function mergeArrays(a, b) { const n = a.length; const m = b.length; const idx = kthSmallest(a, b, n);
// Move all smaller elements in a[]
for (let i = idx; i < n; i++) {
[a[i], b[i - idx]] = [b[i - idx], a[i]];
}
// Sort both a[] and b[]
a.sort((x, y) => x - y);
b.sort((x, y) => x - y);}
// Driver code const a = [1, 5, 9, 10, 15, 20]; const b = [2, 3, 8, 13]; mergeArrays(a, b);
console.log(a.join(" ")); console.log(b.join(" "));
`
Output
1 2 3 5 8 9 10 13 15 20
**Time Complexity: O(log(m) + m*log(m) + n*log(n)), where **n and **m are sizes of **a[] and **b[] respectively.
**Auxiliary Space: O(1)
**Further Optimization: We can optimize the first step to O(log(min(m, n))) by picking the smaller array for binary search.
[Better Approach 2] By Swap and Sort
Actually we can use the previous approach without finding the **pivot index. We just need to swap the **rightmost element in a[] with **leftmost element in b[], then second rightmost element in a[] with second leftmost element in b[] and so on. This will continue until the selected element from a[] is larger than selected element from b[].
When we reach at the **pivot index this condition fails automatically and we will stop here. Now sort both the arrays to maintain the order.
C++ `
#include #include #include using namespace std;
void mergeArrays(vector& a, vector& b) { int i = a.size() - 1, j = 0;
// swap smaller elements from b[]
// with larger elements from a[]
while (i >= 0 && j < b.size() && a[i] > b[j]) {
swap(a[i--], b[j++]);
}
// Sort both arrays
sort(a.begin(), a.end());
sort(b.begin(), b.end());}
int main() { vector a = {1, 5, 9, 10, 15, 20}; vector b = {2, 3, 8, 13}; mergeArrays(a, b);
for (int ele: a)
cout << ele << " ";
cout << "\n";
for (int ele: b)
cout << ele << " ";
return 0;}
C
#include <stdio.h> #include <stdlib.h>
int cmp(const void* a, const void* b) { return ((int)a - (int)b); }
void mergeArrays(int* a, int* b, int n, int m) { int i = n - 1, j = 0;
// Swap smaller elements from b[] with
// larger elements from a[]
while (i >= 0 && j < m) {
if (a[i] < b[j])
i--;
else {
int temp = b[j];
b[j] = a[i];
a[i] = temp;
i--;
j++;
}
}
// Sort both arrays
qsort(a, n, sizeof(int), cmp);
qsort(b, m, sizeof(int), cmp);}
int main() { int a[] = {1, 5, 9, 10, 15, 20}; int b[] = {2, 3, 8, 13}; int n = sizeof(a) / sizeof(a[0]); int m = sizeof(b) / sizeof(b[0]); mergeArrays(a, b, n, m);
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
for (int i = 0; i < m; i++)
printf("%d ", b[i]);
return 0;}
Java
import java.util.Arrays;
class GfG { static void mergeArrays(int[] a, int[] b) { int i = a.length - 1, j = 0;
// Swap smaller elements from b[] with
// larger elements from a[]
while (i >= 0 && j < b.length) {
if (a[i] < b[j])
i--;
else {
int temp = b[j];
b[j] = a[i];
a[i] = temp;
i--;
j++;
}
}
// Sort both arrays
Arrays.sort(a);
Arrays.sort(b);
}
public static void main(String[] args) {
int[] a = {1, 5, 9, 10, 15, 20};
int[] b = {2, 3, 8, 13};
mergeArrays(a, b);
for (int ele : a)
System.out.print(ele + " ");
System.out.println();
for (int ele : b)
System.out.print(ele + " ");
}}
Python
def mergeArrays(a, b): i = len(a) - 1 j = 0
# Swap smaller elements from b[] with
# larger elements from a[]
while i >= 0 and j < len(b):
if a[i] < b[j]:
i -= 1
else:
a[i], b[j] = b[j], a[i]
i -= 1
j += 1
# Sort both arrays
a.sort()
b.sort()if name == "main": a = [1, 5, 9, 10, 15, 20] b = [2, 3, 8, 13] mergeArrays(a, b)
for ele in a:
print(ele, end=' ')
print()
for ele in b:
print(ele, end=' ')C#
using System;
class GfG { static void mergeArrays(int[] a, int[] b) { int i = a.Length - 1, j = 0;
// Swap smaller elements from b[] with
// larger elements from a[]
while (i >= 0 && j < b.Length) {
if (a[i] < b[j])
i--;
else {
int temp = b[j];
b[j] = a[i];
a[i] = temp;
i--;
j++;
}
}
// Sort both arrays
Array.Sort(a);
Array.Sort(b);
}
static void Main() {
int[] a = {1, 5, 9, 10, 15, 20};
int[] b = {2, 3, 8, 13};
mergeArrays(a, b);
foreach (int ele in a)
Console.Write(ele + " ");
Console.WriteLine();
foreach (int ele in b)
Console.Write(ele + " ");
}}
JavaScript
function mergeArrays(a, b) { let i = a.length - 1; let j = 0;
// Swap smaller elements from b[] with
// larger elements from a[]
while (i >= 0 && j < b.length) {
if (a[i] < b[j]) {
i--;
} else {
[a[i], b[j]] = [b[j], a[i]];
i--;
j++;
}
}
// Sort both arrays
a.sort((x, y) => x - y);
b.sort((x, y) => x - y);}
// Driver Code const a = [1, 5, 9, 10, 15, 20]; const b = [2, 3, 8, 13]; mergeArrays(a, b);
console.log(a.join(" ")); console.log(b.join(" "));
`
Output
1 2 3 5 8 9 10 13 15 20
**Time Complexity: O((m+n) + m*log(m) + n*log(n)), where **n and **m are sizes of **a[] and **b[] respectively.
**Auxiliary Space: O(1)
[Better Approach 2] Using Gap method
The idea is to assume the two arrays as a single continuous array of size **n + m and sort it using gap method of shell sort. Here we need to adjust the indices according to whether it lies in **a[] or **b[]. And if indices lies in b[] then adjust the indices by subtracting **n from it.
- Assume the two arrays as a single continuous array of size **n + m and find the gap value, **gap = ceil((n + m)/2 )
- Until the gap doesn't become zero, perform the following operations:
- Take two pointers **left and **right and place them at index 0 and (left + gap) index respectively.
- Run a while loop until right is less than **len (n + m).
- Their are 3 different cases inside this while loop.
* **When both the left and right pointers are in the a[]. Then compare the a[left] and a[right]. If a[left] > a[right], then swap the a[left] and a[right].
* **When the left pointer is in a[] and right pointer is in b[] and if a[left] > b[right-m], then swap the a[left] and b[right-m].
* **When both the left and right pointers are in the b[] and if a[left] > b[right-m], then swap the a[left] and b[right-m]. - If the right pointer reaches the end i.e. m + n, decrement the gap value by ceil(gap/2). C++ `
#include #include #include using namespace std;
void mergeArrays(vector& a, vector& b) { int n = a.size(); int m = b.size(); int gap = (n + m + 1) / 2;
while (gap > 0) {
int i = 0, j = gap;
while (j < n + m) {
// If both pointers are in the first array a[]
if (j < n && a[i] > a[j]) {
swap(a[i], a[j]);
}
// If first pointer is in a[] and
// the second pointer is in b[]
else if (i < n && j >= n && a[i] > b[j - n]) {
swap(a[i], b[j - n]);
}
// Both pointers are in the second array b
else if (i >= n && b[i - n] > b[j - n]) {
swap(b[i - n], b[j - n]);
}
i++;
j++;
}
// After operating for gap of 1 break the loop
if (gap == 1) break;
// Calculate the next gap
gap = (gap + 1) / 2;
}}
int main() { vector a = {1, 5, 9, 10, 15, 20}; vector b = {2, 3, 8, 13}; mergeArrays(a, b);
for (int ele: a)
cout << ele << " ";
cout << "\n";
for (int ele: b)
cout << ele << " ";
return 0;}
C
#include <stdio.h>
void mergeArrays(int* a, int* b, int n, int m) { int gap = (n + m + 1) / 2;
while (gap > 0) {
int i = 0, j = gap;
while (j < n + m) {
// If both pointers are in the first array a[]
if (j < n && a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
// If first pointer is in a[] and
// the second pointer is in b[]
else if (i < n && j >= n && a[i] > b[j - n]) {
int temp = a[i];
a[i] = b[j - n];
b[j - n] = temp;
}
// Both pointers are in the second array b
else if (i >= n && b[i - n] > b[j - n]) {
int temp = b[i - n];
b[i - n] = b[j - n];
b[j - n] = temp;
}
i++;
j++;
}
// After operating for gap of 1 break the loop
if (gap == 1) break;
// Calculate the next gap
gap = (gap + 1) / 2;
}}
int main() { int a[] = {1, 5, 9, 10, 15, 20}; int b[] = {2, 3, 8, 13}; int n = sizeof(a) / sizeof(a[0]); int m = sizeof(b) / sizeof(b[0]); mergeArrays(a, b, n, m);
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
for (int i = 0; i < m; i++)
printf("%d ", b[i]);
return 0;}
Java
import java.util.Arrays;
class GfG { static void mergeArrays(int[] a, int[] b) { int n = a.length; int m = b.length; int gap = (n + m + 1) / 2;
while (gap > 0) {
int i = 0, j = gap;
while (j < n + m) {
// If both pointers are in the first array a[]
if (j < n && a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
// If first pointer is in a[] and
// the second pointer is in b[]
else if (i < n && j >= n && a[i] > b[j - n]) {
int temp = a[i];
a[i] = b[j - n];
b[j - n] = temp;
}
// Both pointers are in the second array b
else if (i >= n && b[i - n] > b[j - n]) {
int temp = b[i - n];
b[i - n] = b[j - n];
b[j - n] = temp;
}
i++;
j++;
}
// After operating for gap of 1 break the loop
if (gap == 1) break;
// Calculate the next gap
gap = (gap + 1) / 2;
}
}
public static void main(String[] args) {
int[] a = {1, 5, 9, 10, 15, 20};
int[] b = {2, 3, 8, 13};
mergeArrays(a, b);
for (int ele : a)
System.out.print(ele + " ");
System.out.println();
for (int ele : b)
System.out.print(ele + " ");
}}
Python
def mergeArrays(a, b): n = len(a) m = len(b) gap = (n + m + 1) // 2
while gap > 0:
i = 0
j = gap
while j < n + m:
# If both pointers are in the first array a[]
if j < n and a[i] > a[j]:
a[i], a[j] = a[j], a[i]
# If first pointer is in a[] and
# the second pointer is in b[]
elif i < n and j >= n and a[i] > b[j - n]:
a[i], b[j - n] = b[j - n], a[i]
# Both pointers are in the second array b
elif i >= n and b[i - n] > b[j - n]:
b[i - n], b[j - n] = b[j - n], b[i - n]
i += 1
j += 1
# After operating for gap of 1 break the loop
if gap == 1:
break
# Calculate the next gap
gap = (gap + 1) // 2if name == "main": a = [1, 5, 9, 10, 15, 20] b = [2, 3, 8, 13] mergeArrays(a, b)
for ele in a:
print(ele, end=' ')
print()
for ele in b:
print(ele, end=' ')C#
using System;
class GfG { static void mergeArrays(int[] a, int[] b) { int n = a.Length; int m = b.Length; int gap = (n + m + 1) / 2;
while (gap > 0) {
int i = 0, j = gap;
while (j < n + m) {
// If both pointers are in the first array a[]
if (j < n && a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
// If first pointer is in a[] and
// the second pointer is in b[]
else if (i < n && j >= n && a[i] > b[j - n]) {
int temp = a[i];
a[i] = b[j - n];
b[j - n] = temp;
}
// Both pointers are in the second array b
else if (i >= n && b[i - n] > b[j - n]) {
int temp = b[i - n];
b[i - n] = b[j - n];
b[j - n] = temp;
}
i++;
j++;
}
// After operating for gap of 1 break the loop
if (gap == 1) break;
// Calculate the next gap
gap = (gap + 1) / 2;
}
}
static void Main() {
int[] a = {1, 5, 9, 10, 15, 20};
int[] b = {2, 3, 8, 13};
mergeArrays(a, b);
foreach (int ele in a)
Console.Write(ele + " ");
Console.WriteLine();
foreach (int ele in b)
Console.Write(ele + " ");
}}
JavaScript
function mergeArrays(a, b) { let n = a.length; let m = b.length; let gap = Math.floor((n + m + 1) / 2);
while (gap > 0) {
let i = 0;
let j = gap;
while (j < n + m) {
// If both pointers are in the first array a[]
if (j < n && a[i] > a[j]) {
[a[i], a[j]] = [a[j], a[i]];
}
// If first pointer is in a[] and
// the second pointer is in b[]
else if (i < n && j >= n && a[i] > b[j - n]) {
[a[i], b[j - n]] = [b[j - n], a[i]];
}
// Both pointers are in the second array b
else if (i >= n && b[i - n] > b[j - n]) {
[b[i - n], b[j - n]] = [b[j - n], b[i - n]];
}
i++;
j++;
}
// After operating for gap of 1 break the loop
if (gap === 1) break;
// Calculate the next gap
gap = Math.floor((gap + 1) / 2);
}}
// Driver Code const a = [1, 5, 9, 10, 15, 20]; const b = [2, 3, 8, 13]; mergeArrays(a, b);
console.log(a.join(" ")); console.log(b.join(" "));
`
Output
1 2 3 5 8 9 10 13 15 20
**Time Complexity: O(m+n)*O(log(m+n)), the outer loop runs from m+n to 1 and its everytime divided by 2. So, outer loop complexity is O(log(m+n)). The inner loop time complexity is O(m+n).
**Auxiliary Space : O(1)
**Related Articles:
Merge two sorted arrays
Merge k sorted arrays | Set 1
Efficiently merging two sorted arrays with O(1) extra space