Median of Two Sorted Arrays - 寻找两个有序数组的中位数(重)

问题:

There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

解答:

这道题要求的时间复杂度为log(m+n), 那么直接的挨个寻找肯定不能满足需求。一般复杂度为对数的,都要求二分法解决,本题也需要二分法解决。

这道题,可以先转化为在两个有序数组中,寻找第K小的数,k=(m+n)中间数时即可得中位数。

为了寻找第k小的数,假设第k小的数记做x, 我们可以每次排除一半比x小的数,即排除k/2个最小的数,然后在剩余的数组中,寻找第k/2小的数,一直到k==1,则可以得出答案。这就是二分法的思想。

如何排除比k/2个最小的数呢,首先我们选择两个数组中最小的第(k/2)个和(k-k/2)个数(因为k为整数所以(k-k/2)不一定等于k/2), 两者之中,比较小的那个数所在的数组,前k/2个数肯定不包含x,也就是说,肯定可以把它排除掉,然后寻找第k/2小的数。

这就相当于将其中的一个数组截断掉(k/2)个数,然后在两个新的数组中,重新寻找第k/2小的数。


情况1:

例如: A = {1,3,5,7,9},    B={ 2,4,6,8,10}  两个数组,寻找第k=5小的数

第一步; k/2 = 2;  k - k/2 = 3

将A组中第2个数 和 数组B中第3个数进行比较, 3 < 6. 那么将第一个数组截断2个数据,排除掉两个数,变成{5,7,9}

递归在A = {5,7,9},    B={ 2,4,6,8,10},两个数组中寻找第3小的数。


第二步: k/2 = 1, k - k/2= 2;

将A组中第1个数,和B组中第2个数,进行比较,5>4. 那么截断B组中的两个数据, 变成{6,8,10};

递归在A = {5,7,9},    B={ 6,8,10},两个数组中寻找第1小的数。

第三步,在两个数组中寻找最小的那个数,直接比较两个数组中的最小值即可。


还可以出现这样一种情况:


第k/2个数和第k-k/2个数相等,那么可以判定,最小的第k个数就是其中的一个。

例如A = {1,3,5,7,9},    B={ 2,4,5,8,10}

寻找第6小的数,那么就可以得知,第k/2 = 3 和k-k/2=3 个数都是 5 那么最小的第k个数就是5.


第三种情况:

截断到最后,其中一个数组全部截断完毕,数组为空,那么只需要再另外一个数组中寻找剩余的最小数。


综上:一直这样递归排除,可以出现两种情况。

1 不断的截断两个数组, k不断的除2, 最后k的值为1, 那么就是在两个数组中寻找最小的那个数,直接比较两个数组最小的值就可以。

2 截断过程中出现两个最小数相等,直接输出。

3  其中有一个数组被完全排除掉,那么直需要再剩余的数组中寻找第K个最小的数就可以。


参考:http://blog.csdn.net/yutianzuijin/article/details/11499917


代码:

class Solution {
public:
	double findKth(int A[], int m, int B[], int n, int k){
		if(m == 0)
			return B[k-1];
		if(k == 1)
			return (A[0]<B[0]? A[0] : B[0]);
		int pa = (k/2<m? k/2 : m);
		int pb = k - pa;
		if(A[pa-1] < B[pb-1])
			return findKth(A+pa, m-pa, B, n, k-pa);
		else if(A[pa-1] > B[pb-1])
		{
			if(m < n-pb)
				return findKth(A, m, B+pb, n-pb, k-pb);
			else
				return findKth(B+pb, n-pb, A, m, k-pb);
		}
		else
			return A[pa-1];
	}

    double findMedianSortedArrays(int A[], int m, int B[], int n) {
		if((m+n)%2 == 1)
		{
			if(m<=n)
				return findKth(A,m,B,n,(m+n)/2+1);
			else
				return findKth(B,n,A,m,(m+n)/2+1);
		}
		else
		{
			if(m<=n)
				return (findKth(A,m,B,n,(m+n)/2) + findKth(A,m,B,n,(m+n)/2+1))/2;
			else
				return (findKth(B,n,A,m,(m+n)/2) + findKth(B,n,A,m,(m+n)/2+1))/2;
		}
    }
};



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值