这个问题很经典,有必要好好梳理一下:
函数的参数设定为,数组A,A的长度m,数组B,B的长度n,需要找的k。
- 如果m + n < k,那么无论如何也找不到满足要求的数了;
- 如果m和n其一为0,那么就应该返回另一个数组的k - 1位置的元素;
- 否则,将A(近似地)平均分为两部分,记其分点下标为i = m / 2,B也如此做,其分点下标为j = n / 2。假设A[i] <= B[j],如果不是这样,那么就将A、B互换,i、j,m、n也需要互换。
在A中,A[i]之后一共有m - i - 1个元素,B[j]及其之后共有n - j个元素。又由于A[i] <= B[j],合并后,A[i]之后(不包括A[i])将至少有m - i - 1 + n - j = (m + n) - (i + j + 1)个元素。这说明,合并后A[i]之前(包括A[i])至多有i + j + 1个元素。如果k > i + j + 1,那么我们要找的元素不可能在A[i]之前,A[i]及其之前的所有元素可以被舍弃。
综上便可以得到代码:
class FindKthIn2Arrays {
private:
int findKthIn2Arrays(int A[], int m, int B[], int n, int k) {
if (m + n < k)
return -1;
if (m == 0)
return B[k - 1];
if (n == 0)
return A[k - 1];
int *p, *q, i, j, t;
i = m / 2;
j = n / 2;
if (A[i] <= B[j]) {
p = A;
q = B;
}
else {
p = B;
q = A;
swap(i, j);
swap(m, n);
}
t = i + j + 1;
if (k <= t)
return findKthIn2Arrays(p, m, q, j, k);
else
return findKthIn2Arrays(p + i + 1, m - (i + 1), q, n, k - (i + 1));
}
public:
void tester() {
int A[5], B[5];
for (int i = 0; i < 5; ++i) {
A[i] = 2 * i;
B[i] = 2 * i + 1;
}
cout << findKthIn2Arrays(A, 5, B, 5, 2) << endl;
}
};