The intersection of two sorted arrays

后端 未结 8 1467
臣服心动
臣服心动 2020-11-29 02:21

Given two sorted arrays: A and B. The size of array A is La and the size of array B is Lb. How

8条回答
  •  独厮守ぢ
    2020-11-29 03:04

    This is in Java, but it does what you want. It implements variant 3 mentioned in Nazar's answer (a "double" binary search) and should be the fastest solution. I'm pretty sure this beats any kind of "galloping" approach. Galloping just wastes time getting started with small steps while we jump right in with a top-down binary search.

    It's not immediately obvious which complexity class applies here. We do binary searches in the longer array, but never look at the same element twice, so we are definitely within O(m+n).

    This code has been thoroughly tested with random data.

    import java.util.Arrays;
    
    // main function. may return null when result is empty
    static int[] intersectSortedIntArrays(int[] a, int[] b) {
      return intersectSortedIntArrays(a, b, null);
    }
    
    // no (intermediate) waste version: reuse buffer
    static int[] intersectSortedIntArrays(int[] a, int[] b, IntBuffer buf) {
      int i = 0, j = 0, la = lIntArray(a), lb = lIntArray(b);
      
      // swap if a is longer than b
      if (la > lb) {
        int[] temp = a; a = b; b = temp;
        int temp2 = la; la = lb; lb = temp2;
      }
      
      // special case zero elements
      if (la == 0) return null;
      
      // special case one element
      if (la == 1)
        return Arrays.binarySearch(b, a[0]) >= 0 ? a : null;
        
      if (buf == null) buf = new IntBuffer(); else buf.reset();
      intersectSortedIntArrays_recurse(a, b, buf, 0, la, 0, lb);
      return buf.toArray();
    }
    
    static void intersectSortedIntArrays_recurse(int[] a, int[] b, IntBuffer buf, int aFrom, int aTo, int bFrom, int bTo) {
      if (aFrom >= aTo || bFrom >= bTo) return; // nothing to do
      
      // start in the middle of a, search this element in b
      int i = (aFrom+aTo)/2;
      int x = a[i];
      int j = Arrays.binarySearch(b, bFrom, bTo, x);
    
      if (j >= 0) {
        // element found
        intersectSortedIntArrays_recurse(a, b, buf, aFrom, i, bFrom, j);
        buf.add(x);
        intersectSortedIntArrays_recurse(a, b, buf, i+1, aTo, j+1, bTo);
      } else {
        j = -j-1;
        intersectSortedIntArrays_recurse(a, b, buf, aFrom, i, bFrom, j);
        intersectSortedIntArrays_recurse(a, b, buf, i+1, aTo, j, bTo);
      }
    }
    
    
    static int lIntArray(int[] a) {
      return a == null ? 0 : a.length;
    }
    
    
    static class IntBuffer {
      int[] data;
      int size;
      
      IntBuffer() {}
      IntBuffer(int size) { if (size != 0) data = new int[size]; }
      
      void add(int i) {
        if (size >= lIntArray(data))
          data = resizeIntArray(data, Math.max(1, lIntArray(data)*2));
        data[size++] = i;
      }
      
      int[] toArray() {
        return size == 0 ? null : resizeIntArray(data, size);
      }
      
      void reset() { size = 0; }
    }
    
    static int[] resizeIntArray(int[] a, int n) {
      if (n == lIntArray(a)) return a;
      int[] b = new int[n];
      arraycopy(a, 0, b, 0, Math.min(lIntArray(a), n));
      return b;
    }
    
    static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) {
      if (n != 0)
        System.arraycopy(src, srcPos, dest, destPos, n);
    }
    

提交回复
热议问题