在两个有序数组中寻找第k个元素

这个问题很经典,有必要好好梳理一下:

函数的参数设定为,数组A,A的长度m,数组B,B的长度n,需要找的k。

  1. 如果m + n < k,那么无论如何也找不到满足要求的数了;
  2. 如果m和n其一为0,那么就应该返回另一个数组的k - 1位置的元素;
  3. 否则,将A(近似地)平均分为两部分,记其分点下标为i = m / 2,B也如此做,其分点下标为j = n / 2。假设A[i] <= B[j],如果不是这样,那么就将A、B互换,i、j,m、n也需要互换。
如此,B[j]将不小于B中它之前的所有元素,并且也不小于A[i],进而推得不小于A中A[i]前的所有元素。这说明,如果我们将A、B数组合并,B[j]前(不包括B[j])将至少有i + j + 1个元素。如果k <= i + j + 1,我们要找的元素一定在B[j]的前面,合并后排在B[j]后的元素将不可能是解,将其直接抛弃,而我们此时能确定的合并后一定排在B[j]后的元素就是B中B[j]后的元素,将其舍弃。

在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;
	}
};


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值