您的位置:首页 > 其它

leetcode-Median of Two Sorted Arrays

2015-05-21 12:36 295 查看
描述:

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)).

分析:

其实这题更通用的形式是,给定两个已经排好序的数组,找到两者所有元素中第k大的元素。

O(m+n)的解法比较直观,直接merge两个数组,然后取第k个元素即可。

不过我们仅仅需要第k大的元素,是不需要“排序”这么复杂的操作的。可以用一个计数器,记录当前已经找到第m大的元素,同时我们使用两个指针pA和pB,分别指向A和B数组的第一个元素,使用类似于merge sort的原理,如果数组A当前元素小,那么pA++,同时m++;如果数组B当前元素小,那么pB++,m++。最终当m等于k的时候,就得到了我们的答案,O(k)时间,O(1)空间。如果当k接近m+n的时候,这个方法还是O(m+n)的。

实现代码:

#include<stdio.h>
static int g_InvlidInput = 0;
int find_kth(int A[],int m, int B[], int n,int k)
{
if((m+n)<k)
{
g_InvlidInput = 1;
return -1;
}
int kth = 0,kthindex = 0,Aindex = 0,Bindex = 0;
int *pA = A;
int *pB = B;
while((kthindex < k) && (Aindex < m) && (Bindex < n))
{
if(pA[Aindex] <pB[Bindex])
{
kth = pA[Aindex];
Aindex++;
}else
{
kth = pB[Bindex];
Bindex++;
}
kthindex++;
}
if(kthindex == k)
return kth;
else
{
if(Aindex == m) return pB[Bindex+k-kthindex];
if(Bindex == n) return pA[Aindex+k-kthindex];
}
}

//test
int main()
{
int A[] ={1,4,5,7,9,22,44,78};
int B[] ={2,4,7,11,12,23,45};
int result = find_kth(A,8,B,7,8);
if(g_InvlidInput)
printf("Invaild Input!");
else
printf("%d\n",result);
return 0;
}


除了这个方案,还有没有更好的方案呢?有。我们可以考虑从k入手。如果我们每次都删除一半呢》由于A和B都是有序的,我们应该充分利用这里面的信息,类似于二分查找,也是充分利用了“有序”。

假设A和B的元素个数都大于k/2,我们将A的第k/2个元素(即A[k/2-1])和B的第k/2个元素(即B[k/2-1])进行比较,有以下三种情况(为了简化这里先假设k为偶数,所得到的结论对于k为奇数也是成立的):

A[k/2-1] == B[k/2-1]

A[k/2-1] > B[k/2-1]

A[k/2-1] < B[k/2-1]

如果A[k/2-1] < B[k/2-1] ,意味着A[0]到A[k/2-1]的元素肯定在AUB的top k元素的范围内,也就是说,A[K/2-1]不可能大于AUB的第k大元素。

因此,我们可以放心的删除A数组的这k/2个元素。同理,当A[k/2-1] > B[k/2-1]时,可以删除B数组的k/2个元素。

当A[k/2-1] == B[k/2-1]时,说明找到了第k大的元素,直接返回A[k/2-1]或B[k/2-1]即可。

因此,我们可与写一个递归函数,那么函数该什么时候终止呢?

当A或B是空时,直接返回B[k-1]或A[k-1];

当k=1时,返回min(A[0],B[0]);

当A[k/2-1] == B[k/2-1]时,返回A[k/2-1]或B[k/2-1]

实现代码:

#include<stdio.h>
int min(int a, int b)
{
if(a>b)
return b;
else
return a;
}
int find_kth(int A[],int m, int B[], int n,int k)
{
//保证m比n小
if(m >n) return find_kth(B,n,A,m,k);
if(m == 0) return B[k-1];
if(k == 1) return min(A[0],B[0]);

//将k拆分成两个部分
int pa = min(k/2,m),pb = k -pa;
if(A[pa-1] < B[pb-1])
return find_kth(A+pa,m-pa,B,n,k-pa);
else if( A[pa-1] >B[pb-1])
return find_kth(A,m,B+pb,n-pb,k-pb);
else
return A[pa-1];
}

//test
int main()
{
int A[] ={1,4,5,7,9,22,44,78};
int B[] ={2,4,7,11,12,23,45};
int result = find_kth(A,8,B,7,10);
printf("%d\n",result);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: