Wednesday, January 25, 2012

Merge Sorted arrays with empty slots

There are two sorted arrays A1 and A2. Array A1 is full where as array A2 is partially empty and number of empty slots are just enough to accommodate all elements of A1. Write a program to merge the two sorted arrays to fill the array A2. You cannot use any additional memory and expected run time is O(n).

Question 2:
Merge two sorted arrays without extra space.

Method 1:Moving To End
Concept:
Let first array be mPlusN[] and other array be N[]
1) Move m elements of mPlusN[] to end.
2) Start from nth element of mPlusN[] and 0th element of N[] and merge them
    into mPlusN[].
 For Example

  int mPlusN[9] = {2, 8, NA, NA, NA, 13, NA, 15, 20};
  int N[] = {5, 7, 9, 25};
Output: int mPlusN[9]={2,5,7,8,9,13,15,20,25}
Code:
#define NA -1
void moveToEnd(int mPlusN[], int size)
{
  int i = 0, j = size - 1;
  for (i = size-1; i >= 0; i--)
    if(mPlusN[i] != NA)
    {
      mPlusN[j] = mPlusN[i];
      j--;
    }
}

int merge(int mPlusN[], int N[], int m, int n)
{
  int i = n;
  int j = 0;
  int k = 0;
  while(k <= (m+n))
  {
    if((i < (m+n) && mPlusN[i] <= N[j]) || ( j == n))
    {
      mPlusN[k] = mPlusN[i];
      k++;
      i++;
    }
    else
    {
      mPlusN[k] = N[j];
      k++;
      j++;
    }
  }
}
Time Complexity:O(m+n)

Alternatively [ Better Solution ],
We will start with three pointers: a_end, a_tail and b_tail where;
a_end - last memory location of A
a_tail - last non-zero element of A
b_tail - last non-zero element of B

We start the merge from the end by comparing elements at a_tail and b_tail and putting the greater one at a_end.

#include<stdio.h>
#include<stdlib.h>

void mergeArrays(int* A, int* B, int a_size, int b_size)
{
    int a_end = a_size + b_size - 1;
    int a_tail = a_size - 1;
    int b_tail = b_size - 1;

    while((a_tail >= 0) && (b_tail >= 0))
    {
        if(B[b_tail] > A[a_tail])
            A[a_end--] = B[b_tail--];
        else
            A[a_end--] = A[a_tail--];
    }

    while(b_tail >=0)
        A[a_end--] = B[b_tail--];
}

int main()
{
    int A[200] = {0,};
    int B[50] = {0,};
    int i;

    for(i=80; i<230; i++)
        A[i-80] = i*2;

    for(i=0; i<50; i++)
        B[i] = i;

    mergeArrays(A, B, 150, 50);

    for(i=0; i<200; i++)
        printf("A[%d] =  %d\n", i, A[i]);
    getchar();
    return 0;
}

Method 2:Merge inplace
In this method we progressively compare the elements of 1st array (of size X Y) with the first element of the 2nd array (of size Y). Since the numbers are stored in increasing order if the number of 1st array is smaller than the 2nd array then it will come at a smaller index in the final list otherwise we exchange the two elements.
Now the element exchange may result in the 2nd array having a greater number and hence it will have to be shifted to the correct position by successively comparing in the 2nd array. This procedure does not make use of extra memory.
Finally both the arrays will be sorted and contain elements in increasing order with earlier elements in the 1st array and the larger elements in the 2nd array, then we just need to append the 2nd array to the end of 1st array.

Code:
Let a1 contain X+Y elements and a2 contain X elements. L1=X+Y L2=Y
  for(int i=0;i < l1;i++)
    {
            if(a1[i] > a2[0])
            {
                           swap(a1[i],a2[0]);
                           for(int j=1;j < l2;j++)
                           {
                                   if(a2[j-1] > a2[j])
                                      swap(a2[j-1],a2[j]);
                                   else
                                       break;
                           }
            }
    }
    int y=l1-l2;
    for(int i=0;i < l1;i++)
        a1[i]=a2[i-y];

1 comment:

  1. http://www.geeksforgeeks.org/archives/2838
    http://www.geeksforgeeks.org/archives/2398

    ReplyDelete