Merge two arrays and sort the final one

前端 未结 11 817
情歌与酒
情歌与酒 2021-01-15 17:42

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 to

相关标签:
11条回答
  • 2021-01-15 18:12

    You should do something like insertion sort. As both the arrays are sorted (except -1s), the smallest number in array2 will be placed somewhere between first element and the first -1, 2nd element of array2 will be placed somewhere anywhere after the 1st -1 in array1 and before or at the 2nd -1 in array1 and so on.

    So you have to insert a particular element of array2 in only a segment of array1 and not the whole array. Also each element of array2 have to consider different segment or subarray of array1. So, effective time complexity of this logic will be O(n+m) where n is the length of array1 and m is the length of array2.

    0 讨论(0)
  • 2021-01-15 18:13

    Let me re-phrase three most important aspects of the task:

    • Both arrays are sorted and include positive integers (except -1 place-holders in Array1)
    • The -1 is meaningless placeholder (its position in Array1 is random)
    • Array1 length equals output array length

    Pseudo logic:

    • parse both array1 and array2 from the first position to end of array
    • ignore -1 values in array1
    • if array1[current position] <= array2[current position] then write array1[current position] into merged array and move to next position in array1; otherwise apply same for array2

    Code example:

                public static void AMerge()
            {
                int[] array1 = new int[] { 3, 6, -1, 11, 15, -1, 23, 34, -1, 42 };
                int[] array2 = new int[] { 1, 9, 28 };
                int[] arrayMerged = new int[array1.Length];
    
                int array1Index = 0;
                int array2Index = 0;
    
                for (int arrayMergedIndex = 0; arrayMergedIndex < array1.Length; arrayMergedIndex++)
                {
                    while (array1[array1Index] == -1) array1Index++; //ignore -1 placeholders
                    if ((array1Index < array1.Length && array2Index >= array2.Length) 
                        || array1[array1Index] <= array2[array2Index])  //choose which array will provide current merged value
                    {
                        arrayMerged[arrayMergedIndex] = array1[array1Index];
                        array1Index++;
                    }
                    else
                    {
                        arrayMerged[arrayMergedIndex] = array2[array2Index];
                        array2Index++;
                    }
                }
    
                char[] charsToTrim = { ',', ' '};
                string arrayMergedString = "{";
                foreach (int f in arrayMerged) arrayMergedString += f.ToString() + " ";
                arrayMergedString = arrayMergedString.TrimEnd(charsToTrim) + "}";
                Console.WriteLine(arrayMergedString);
                Console.ReadKey();
            }
        }
    

    Note:

    • Optimizing for speed => creating new arrayMerged; optimization for space would require moving array1 elements in the else branch
    0 讨论(0)
  • 2021-01-15 18:15

    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 讨论(0)
  • 2021-01-15 18:19

    There is a clean O(N) in-place solution.

    First "pack" arrayOne by moving all -1 (-- below) to the front. This takes a single backward pass.

    Then perform a merge by iteratively moving the smallest element among arrayTwo and the tail of arrayOne and overwriting the next --. The gap will narrow down but there will always remain room for the elements of arrayTwo.

     3,  6, --, 11, 15, --, 23, 34, --, 42
     1,  9, 28
    

    Packing:

     3,  6, --, 11, 15, --, 23, 34, --, 42
    
     3,  6, --, 11, 15, --, 23, --, 34, 42
    
     3,  6, --, 11, 15, --, --, 23, 34, 42
    
     3,  6, --, 11, --, --, 15, 23, 34, 42
    
     3,  6, --, --, --, 11, 15, 23, 34, 42
    
     3, --, --, --,  6, 11, 15, 23, 34, 42
    
     --, --, --, 3,  6, 11, 15, 23, 34, 42
    

    Merging:

      --, --, --,  3,  6, 11, 15, 23, 34, 42
       1,  9, 28
    
       1, --, --,  3,  6, 11, 15, 23, 34, 42
      --,  9, 28
    
       1,  3, --, --,  6, 11, 15, 23, 34, 42
      --,  9, 28
    
       1,  3,  6, --, --, 11, 15, 23, 34, 42
      --,  9, 28
    
       1,  3,  6,  9, --, 11, 15, 23, 34, 42
      --, --, 28
    
       1,  3,  6,  9, 11, --, 15, 23, 34, 42
      --, --, 28
    
       1,  3,  6,  9, 11, 15, --, 23, 34, 42
      --, --, 28
    
       1,  3,  6,  9, 11, 15, 23, --, 34, 42
      --, --, 28
    
       1,  3,  6,  9, 11, 15, 23, 28, 34, 42
      --, --, --
    
    0 讨论(0)
  • 2021-01-15 18:24

    Couldn't it be something like

    compare each item of arrayTwo with each item of arrayOne If it comes to bigger that that of arrayOne, insert the item and while iterating arrayOne delete all the -1 .

    0 讨论(0)
  • 2021-01-15 18:25

    You should use merge function from Merge sort, and modify it so that it doesn't create a new array, but instead uses array1, and perform translation, after insertion of an element from array2, that will shift elements to the right until the next -1, and thus overwrite the -1.

    0 讨论(0)
提交回复
热议问题