Thursday 30 August 2018

Merge two tables and sort the last one

In an interview I was asked the following question. I am given two arrays, both of them are sorted.

BUT
Array 1 will have few -1's and Array 2 will have total numbers as the total number of -1's in Array 1.
So in the below example array1 has three -1's hence array2 has 3 numbers.
let say
var arrayOne = [3,6,-1,11,15,-1,23,34,-1,42];
var arrayTwo = [1,9,28];

Both of the arrays will be sorted.
Now I have to write a program that will merge arrayTwo in arrayOne by replacing -1's, and arrayOne should be in sorted order.
So the output will be
arrayOne = [ 1,3, 6, 9, 11, 15, 23, 28 ,34, 42 ]

Sorting should be done without use of any sort API.
I have written a following code
function puzzle01() {
  var arrayOne = [3, 6, -1, 11, 15, -1, 23, 34, -1, 42];
  var arrayTwo = [1, 9, 28];
  var array1Counter = 0,
    isMerged = false;

  console.log(" array-1 ", arrayOne);
  console.log(" array-2 ", arrayTwo);

  for (var array2Counter = 0; array2Counter < arrayTwo.length; array2Counter++) {
    isMerged = false;
    while (isMerged === false && array1Counter < arrayOne.length) {

      if (arrayOne[array1Counter] === -1) {
        arrayOne[array1Counter] = arrayTwo[array2Counter];
        isMerged = true;
      }

      array1Counter++;
    }
  } //for

  console.log(" array-1 + array-2 ", arrayOne);
  bubbleSort(arrayOne);
  console.log(" Sorted array ", arrayOne);
} //puzzle01

puzzle01();

// implementation of bubble sort for sorting the
// merged array
function bubbleSort(arrayOne) {
  var nextPointer = 0,
    temp = 0,
    hasSwapped = false;

  do {
    hasSwapped = false;
    for (var x = 0; x < arrayOne.length; x++) {
      nextPointer = x + 1;
      if (nextPointer < arrayOne.length && arrayOne[x] > arrayOne[nextPointer]) {
        temp = arrayOne[x];
        arrayOne[x] = arrayOne[nextPointer];
        arrayOne[nextPointer] = temp;
        hasSwapped = true;
      }
    } //for
  } while (hasSwapped === true);
} // bubbleSort
The output of the above code is
 array-1  [ 3, 6, -1, 11, 15, -1, 23, 34, -1, 42 ]
 array-2  [ 1, 9, 28 ]
 array-1 + array-2  [ 3, 6, 1, 11, 15, 9, 23, 34, 28, 42 ]
 Sorted array  [ 1, 3, 6, 9, 11, 15, 23, 28, 34, 42 ]

From the above code you can see, I have first merged the two arrays and than sorted the final one.
Just wanted to know, Is there a better solution.
Is there any flaw in my solution.
Please let me know, it will be helpfull.
After reading all your very helpful comments and answers, I found was able to figure out a more faster solution.
Let us take an example
var arrayOne = [3,6,-1,11,15,-1,32,34,-1,42,-1];
var arrayTwo = [1,10,17,56],

Step1: I will iterate through arrayTwo. Take the next element (i.e. '1') and compare with next element of arrayOne (i.e. '3') and compare.
step 2a : If element of array1 is greater than element of array2 than swap array elements. Now go to next element of array1.
OR
step 2b : If element of array1 is equal to -1 than swap array elements. Now go to next element of array2.
step 3: Go to step 1.
So
in the above example
first iteration, array1 = [1,6,-1,11,...] array2 = [3,10,17,56]
second iteration, array1 = [1,3,-1,11,..] array2 = [6,10,17,56]
third iteration, array1 = [1,3,6,11..] array2 = [-1,10,17,56]
fourth iteration array1 = [1,3,6,10,..] array2 = [-1,11,17,56]
and so on.
at the end I will get the output
array1 = [ 1, 3, 6, 10, 11, 15, 17, 32, 34, 42, 56 ]
array2 = [-1,-1,-1]

Please find the code below,
function puzzle02(arrayOne,arrayTwo){
    var array1Counter = 0,
        array2Counter = 0,
        hasMinusOneOccurred = false;

    console.log(" array-1 ",arrayOne);
    console.log(" array-2 ",arrayTwo);  

    while(array2Counter < arrayTwo.length){ // iterate through array2

        do{
            if(arrayOne[array1Counter] === -1){ // if -1 occurred in array1
                hasMinusOneOccurred = true;

                // swaping numbers at current position of array1
                // with current position of array2
                swap(arrayOne,arrayTwo,array1Counter,array2Counter);

                // recheck if the current value is greater than other values
                // of array1
                if(recheckAndSort(arrayOne,array1Counter) === true){
                    array1Counter = -1;// recheck array1 from start
                }else{
                    // recheck the current array1 counter, for doing so go 1 count back
                    // so that even if the counter is incremented it points to current
                    // number itself
                    array1Counter--;
                }

            }else if(arrayOne[array1Counter] > arrayTwo[array2Counter]){
                swap(arrayOne,arrayTwo,array1Counter,array2Counter);
            }else{
                array1Counter++;
                continue;
            }

            array1Counter++;
        }while(hasMinusOneOccurred === false); // end of do-while

        array2Counter++;
        hasMinusOneOccurred = false;

    }//end of while

    console.log(" Sorted array ",arrayOne);

    function swap(arr1,arr2,arr1Index,arr2Index){
        var temp = arr2[arr2Index];
        arr2[arr2Index] = arr1[arr1Index];
        arr1[arr1Index] = temp;
    }// end of swap 

    // this method is call if -1 occures in array1
    function recheckAndSort(arrayOne,array1Counter){
        var isGreaterVal = true,
            prevCounter = 0,
            nextCounter = 0,
            temp = 0,
            recheckFromStart = false;

        if(array1Counter === 0){ // if -1 occurred at first position of array1.

            // flag to check if -1 occurrec at first position
            // if yes, iterate array1 from start
            recheckFromStart = true; 

            // iterate forward to check wether any numbers are less than current position,
            // if yes than move forward
            for(var j = 0; isGreaterVal; j++){
                nextCounter = j + 1;

                if(arrayOne[nextCounter] === -1){
                    // swaping numbers of array1 between next to current
                    swap(arrayOne,arrayOne,nextCounter,j);
                    isGreaterVal = true; 

                }else if(arrayOne[nextCounter] < arrayOne[j]){
                    // swaping numbers of array1 between next to current
                    swap(arrayOne,arrayOne,nextCounter,j);
                    isGreaterVal = true;

                }else{
                    isGreaterVal = false;
                }

             }//end of for

         }else{// if -1 occurred in the middle position of array1 and is been swaped then
            // iterate backwards to check if any number less then current position exists,
            // if yes than shift backwards.
            for(var i = array1Counter; isGreaterVal; i--){
                prevCounter = i - 1;

                if(arrayOne[prevCounter] > arrayOne[i]){

                    // swaping numbers of array1 between previous to current
                    swap(arrayOne,arrayOne,prevCounter,i);
                    isGreaterVal = true;
                }else{
                    isGreaterVal = false;
                }

            }// end of for
        }

        return recheckFromStart;
    }// end of recheckAndSort
} // end of puzzle02

After calling the above function
puzzle02([3,6,-1,11,15,-1,32,34,-1,42,-1],[1,10,17,56]);

The output of above code is,
 array-1  [ 3, 6, -1, 11, 15, -1, 32, 34, -1, 42, -1 ]
 array-2  [ 1, 10, 17, 56 ]
 Sorted array  [ 1, 3, 6, 10, 11, 15, 17, 32, 34, 42, 56 ]

Thanks.

You can try following approach:

Logic

  • Create a new array that will be returned.
  • Check for first element in arrayTwo and keep it in a variable say val.
  • Loop over arrayOne and check if current value is greater than val, push it in array and decrement value of i by 1 to check next value as well with current element.
  • Now check for current element. If it is less than 0, ignore it, else push value to array.
  • Return this array.
function mergeAndSort(a1, a2) {
  var matchCount = 0;
  var ret = [];

  for (var i = 0; i < a1.length; i++) {
    var val = a2[matchCount];
    if (a1[i] > val) {
      ret.push(val)
      matchCount++
      i--;
      continue;
    }
    if (a1[i] > 0) {
      ret.push(a1[i]);
    }
  }
  console.log(ret.join())
  return ret;
}

var arrayOne = [3, 6, -1, 11, 15, -1, 23, 34, -1, 42]
var arrayTwo = [7, 19, 38];
var arrayThree = [1, 9, 28];
var arrayFour = [1,2,5]

mergeAndSort(arrayOne, arrayTwo)
mergeAndSort(arrayOne, arrayThree)
mergeAndSort(arrayOne, arrayFour)
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}
Note: Not putting check for number of elements in arrayTwo as its clearly mentioned in question that it will be same.

0 comments:

Post a Comment