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

_extra_space_using_gap_sort

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] = last

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) {

    // 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 idx

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

  1. Assume the two arrays as a single continuous array of size **n + m and find the gap value, **gap = ceil((n + m)/2 )
  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) // 2

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 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)

Merge two sorted arrays
Merge k sorted arrays | Set 1
Efficiently merging two sorted arrays with O(1) extra space