Searching two arrays for matches, no extra memory

后端 未结 4 577
暖寄归人
暖寄归人 2021-02-02 16:09

I had an interview the other day with Amazon, and a question they asked me was pertaining to the following problem.

Given 2 integer arrays, containing any number of elem

4条回答
  •  甜味超标
    2021-02-02 16:43

    The key is to sort the two arrays in-place. I did a search for "in-place radix sort", and found In-Place Radix Sort. I believe the problem is solvable, at least for Java int[], by applying those ideas to sort each array, bit by bit, then doing the obvious scan.

    Incidentally, I think the correct output for the problem in the question code is 1, 2, 3.

    Here is my implementation, based on the answers to the referenced question:

        public class ArrayMatch {
          public static void main(String[] args) {
            int[] a = { 4, 1, 2, 3, 4 };
            int[] b = { 2, 5, 6, 7, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2 };
            System.out.print("Original problem");
            printMatches(a, b);
            System.out.println();
    
            int[] a1 = { 4, 1, -1234, 2, 3, 4, Integer.MIN_VALUE };
            int[] b1 = { -1234, 2, 5, 6, 7, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2 , Integer.MIN_VALUE, Integer.MAX_VALUE};
            System.out.print("With negatives");
            printMatches(a1, b1);
            System.out.println();
    
          }
    
          // Print all matching elements between the two arrays.
          private static void printMatches(int[] a, int[] b) {
            if (a.length == 0 || b.length == 0) {
              return;
            }
    
            sort(a);
            sort(b);
    
            int i = 0;
            int j = 0;
            while (true) {
              while (a[i] < b[j]) {
                i++;
                if (i == a.length) {
                  return;
                }
              }
              while (a[i] > b[j]) {
                j++;
                if (j == b.length) {
                  return;
                }
              }
    
              if (a[i] == b[j]) {
                System.out.print(" " + a[i]);
    
                do {
                  i++;
                } while (i < a.length && a[i - 1] == a[i]);
    
                do {
                  j++;
                } while (j < b.length && b[j - 1] == b[j]);
              }
    
              if (i == a.length || j == b.length) {
                return;
              }
            }
          }
    
          // In place radix sort.
          private static void sort(int[] in) {
            // Flip the sign bit to regularize the sort order
            flipBit(in, 31);
            sort(in, 0, in.length, 31);
            // Flip back the sign bit back to restore 2's complement
            flipBit(in, 31);
          }
    
          /**
           * Sort a subarray, elements start through end-1 of in, according to the
           * values in firstBit through 0.
           * 
           * @param in
           * @param start
           * @param end
           * @param firstBit
           */
          private static void sort(int[] in, int start, int end, int firstBit) {
            if (start == end) {
              return;
            }
            int mask = 1 << firstBit;
            int zeroCount = 0;
            for (int i = start; i < end; i++) {
              if ((in[i] & mask) == 0) {
                zeroCount++;
              }
            }
    
            int elements = end - start;
            int nextZeroIndex = start;
            int nextOneIndex = start + zeroCount;
    
            int split = nextOneIndex;
    
            if (zeroCount > 0 && zeroCount < elements) {
              while (nextZeroIndex < split) {
                if ((in[nextZeroIndex] & mask) != 0) {
                  // Found a one bit in the zero area, look for its partner in the one
                  // area
                  while ((in[nextOneIndex] & mask) != 0) {
                    nextOneIndex++;
                  }
                  int temp = in[nextZeroIndex];
                  in[nextZeroIndex] = in[nextOneIndex];
                  in[nextOneIndex] = temp;
                  nextOneIndex++;
                }
                nextZeroIndex++;
              }
    
            }
    
            if (firstBit > 0) {
              sort(in, start, split, firstBit - 1);
              sort(in, split, end, firstBit - 1);
            }
    
          }
    
          private static void flipBit(int[] in, int bitNo) {
            int mask = 1 << bitNo;
            for (int i = 0; i < in.length; i++) {
              in[i] ^= mask;
            }
          }
        }
    

提交回复
热议问题