Merge Two Sorted Arrays Without Extra Space

88. Merge Sorted Array

Merge Two Sorted Arrays Without Extra Space

Photo by Minku Kang on Unsplash

Problem Statement - 1

Given two non-decreasing sorted arrays, ‘A’ and ‘B’, having ‘N’ and ‘M’ elements, respectively.

You must merge these arrays, ‘A’ and ‘B’, into a sorted array without using extra space. Of all the 'N + M' sorted elements, array 'A' should contain the first 'N' elements, and array 'B' should have the last 'M' elements.

Note: You must perform the merge operation in place and must not allocate any extra space to merge the two arrays.

For example: When ‘N’ = 4, ‘A’ = {1, 4, 5, 7} and ‘M’ = 3, ‘B’ = {2, 3, 6}. We can merge these two arrays into {1, 2, 3, 4, 5, 6, 7} (The elements of ‘A’ are {1, 2, 3, 4} ). Hence, the answer is {1, 2, 3, 4, 5, 6, 7}.

Solution

Optimal Approach 1

Core logic: Arrange all smaller elements in the left array and greater elements in the right array.

Given that both arrays are sorted, we simply compare the greater elements in the left array with the smaller elements in the right array. If an element in the left array is greater than the corresponding element in the right array, we swap them. This process continues until the element in the left array is smaller than the corresponding element in the right array. Afterwards, we sort the two arrays individually.

Time - O(min(m,n)) + O(mlongm) + O(nlogn)

Space - O(1)

import java.util.Arrays;

public class Solution {
    public static void mergeTwoSortedArraysWithoutExtraSpace(long []a, long []b){
        int m = a.length;
        int n = b.length;

        int i=m-1;
        int j=0;

        while(i>=0 && j<n){
            if(a[i]>b[j]){
                long temp = a[i];
                a[i] = b[j];
                b[j] = temp;
                i-=1;
                j+=1;
            }
            else{
                break;
            }
        }
        Arrays.sort(a);
        Arrays.sort(b);
    }
}

Optimal Approach 2 - Gap Method

The gap method is borrowed from the shell sorting algorithm. Thus, we establish two pointers, denoted as left and right, or i and j respectively. These pointers correspond to the indices of both arrays positioned side by side, with the index of the right array starting at n.

Initially, the gap between i and j is set to the floor value of (m+n)/2. Whenever the element at index i is greater than that at index j, we perform a swap. Following each comparison, regardless of the outcome, we increment both i and j. The process halts once j reaches the value (m+n).

After completing each iteration, we decrease the gap to the floor value of gap/2 and continue the process. If the gap reduces to 1, we proceed with the process one final time before terminating it.

Time - O(log(m+n)) * O(m+n)

Space - O(1)

The outer loop runs for O(log(m+n)) and the inner loop runs for O(n+m)

import java.util.Arrays;

public class Solution {

    public static void checkAndSwap(long[] a, long[] b, int ind1, int ind2){
        if(a[ind1]>b[ind2]){
            long temp = a[ind1];
            a[ind1] = b[ind2];
            b[ind2] = temp;
        }
    }
    public static void mergeTwoSortedArraysWithoutExtraSpace(long []a, long []b){
        int m = a.length;
        int n = b.length;


        int gap = (m+n)/2 + (m+n)%2; // floor value of (m+n)/2

        int i = 0;
        int j = 0;

        while(gap>0){
            i = 0;
            j = i + gap;

            while(j<(m+n)){
                if(j<m){    // both pointers on the left side array
                    checkAndSwap(a,a,i,j);
                }else if(i>=m){ // both pointers on the right side array
                    checkAndSwap(b,b,i-m,j-m);
                }else{ // i is on the left and j is on the right array
                    checkAndSwap(a,b,i,j-m);
                }
                i+=1;
                j+=1;
            }

            if(gap!=1){
                gap = gap/2 + gap%2; //floor value of gap/2
            }else{
                break;
            }
        }
    }
}

Probleme Statement 2

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.

Solution

Here, the task involves combining and sorting the first m elements of nums1 with nums2, and then storing the result back into nums1. The total size of nums1 is m+n, with additional zeros at the end. Both nums1 and nums2 are individually sorted. Hence, our strategy employs a modified version of the merge sort technique. In this approach, we reverse the process, initiating comparisons from the end. If an element is greater, we place it at the end of nums1 and proceed by shifting the pointers to the left until the pointer for the right side reaches an index beyond the bounds, as the second array (nums2) has fewer elements (n) compared to the first array (m+n).

Time - O(n+m)

Space - O(1)

class Solution {
    public void merge(int[] nums1, int m, 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];
                k-=1;
                i-=1;
            }
            else{
                nums1[k]=nums2[j];
                k-=1;
                j-=1;
            }
        }
    }
}