这是在 Java 中,但它可以满足您的需求。它实现了 Nazar 的回答中提到的变体 3(“双重”二进制搜索),应该是最快的解决方案。我很确定这胜过任何一种“疾驰”的方法。飞驰只是浪费时间从小步骤开始,而我们直接进行自上而下的二分搜索。
在这里应用哪种复杂性等级并不是很明显。我们在较长的数组中进行二分搜索,但不会两次查看相同的元素,所以我们肯定在 O(m+n) 之内。
此代码已使用随机数据进行了彻底测试。
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);
}