您的位置:首页 > 其它

Median of Two Sorted Arrays-LeetCode

2014-09-15 14:02 225 查看
题目:

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

题目分析:

当我第一眼看见这题目时,就想到采用归并排序的方式,在两个数组上设立两个指针从头开始逐一比较。直到找到对应的元素为止。下面是自己开始写的代码:

class Solution {
public:

double findMedianSortedArrays(int A[], int m, int B[], int n) {
double result,right;
int num=(n+m+1)/2;
int i=0,j=0,cnt=0;

while(i!=m && j!=n){
if(A[i]<=B[j]){
result=A[i];
i++;
cnt++;
}

else{
result=B[j];
j++;
cnt++;
}

if(cnt==num) {
flag=true;
break;
}
}

while(i!=m){
if(cnt==num) break;
else{
result=A[i];
i++;
cnt++;
}
}

while(j!=n){
if(cnt==num) break;
else{
result=B[j];
j++;
cnt++;
}
}

return result;
}


但是运行之后就发现出现了错误,折腾了很久也没有想明白。后面在网上找资料,才明白自己犯了一个最基本的错误,没有理解Median的含义。当Array的个数是奇数时,Median的值是最中间的一个。当它是偶数时,Median的值是n/2和n/2+1上的值的平均数。

网上的解法普遍都是一样的,看了之后发现这种解法确实很巧妙,貌似是某年考研的算法题,先记录下来。

解题思路:

该方法的核心是将原问题转变成一个寻找第k小的数问题(假设两个原序列升序排列),这样中位数实际上是第(m+n)/2小的数(暂不考虑偶数情形).所以只要解决了第k小的数,原问题就得以解决。

首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,分别代表A和B数组的第k个元素。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k个元素中。也就是说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。(注意:这是该算法最核心的地方)。

反证法:

假设A[k/2-1]大于合并之后的第k小值,我们不妨假定为第(k+1)小值。由于A[k/2-1]小于B[k/2-1],所以B[k/2-1]至少是第(k+2)小值。但实际上,在A中至多存在k/2-1个元素小于A[k/2-1],B中至多存在k/2-1个元素A[k/2-1],所以小于A[k/2-1]的元素个数至多有k/2+k/2-2,小于k,这与A[k/2-1]是k+1的数矛盾。

当A[k/2-1]>B[k/2-1]时也类似。

  当A[k/2-1]==B[k/2-1]时,则我们已经找到第k的元素,也就是这个相等的元素。将其记为m,由于A和B中分别有k/2-1个元素小于m,所以m即是第k小的数。

因此总结起来就是:

如果A或者B为空,则直接返回B[k-1]或者A[k-1]。

如果k为1,我们只需要返回A[0]和B[0]中的较小值。

如果A[k/2-1]=B[k/2-1],返回其中一个。

代码如下:

public:{

dobule findKth(int A[],int m,int  B[],int n,int k){
//m is equal or smaller than n
if(m<n)
return findKth(B,n,A,m,k);
if(m==0)
return B[k-1];
if(k==1)
return min(A[0],B[0]);

int pa=min(k/2,m),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])
return findKth(A,m,B+pb,n-pb,k-pb);
else
return A[pa-1];
}

dobule findMedianSortedArrays(int A[],int m,int B[],int n){
int k=m+n;
if(k & 0x1){
return findKth(A,m,B,n,k/2+1);
}
else{
return (findKth(A,m,B,n,k/2)+findKth(A,m,B,n,k/2+1))/2;
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: