一、题目描述:(408联考真题 2011)
二、算法思想:
分别求两个升序序列A和B的中位数,设为a和b,求序列A和B的中位数过程如下:
1)若a=b,则a或b即为所求中位数,算法结束。
2)若a<b,则舍弃序列A中较小的一半,同时舍弃序列B中较大的一半,要求两次舍弃的长度相等。
3)若a>b,则舍弃序列A中较大的一半,同时舍弃序列B中较小的一半,要求两次舍弃的长度相等。
在保留的两个升序序列中,重复1)、2)、3),直到两个序列中均只含一个元素为止,较小者即为所求。
三、核心代码:
int M_Search(int A[],int B[],int n)
{
//分别定义序列A和B的首位数、末位数和中位数
int s1=0,d1=n-1,m1;
int s2=0,d2=n-1,m2;
while(s1!=d1||s2!=d2)
{
m1=(s1+d1)/2;
m2=(s2+d2)/2;
if(A[m1]==B[m2])
{
return A[m1];//满足1)
}
if(A[m1]<B[m2])//满足2)
{
if((s1+d1)%2==0)//若元素的个数为奇数
{
s1=m1;//舍弃A中点以前的数
d2=m2;//舍弃B中点以后的数
}
else//若元素的个数为偶数
{
s1=m1+1;//舍弃A中点及以前的数
d2=m2;//舍弃B中点以后的数
}
}
else//满足条件3)
{
if((s1+d1)%2==0)//若元素的个数为奇数
{
d1=m1;//舍弃A中点以后的数
s2=m2;//舍弃B中点以前的数
}
else//若元素的个数为偶数
{
d1=m1;//舍弃A中点以后的数
s2=m2+1;//舍弃B中点及以前的数
}
}
}
return A[s1]<B[s2]?A[s1]:B[s2];
}
四、完整代码:
#include<stdio.h>
int M_Search(int A[],int B[],int n);
void Print(int A[],int n);
int main()
{
int A[5]={11,13,15,17,19};
int B[5]={2,4,6,8,20};
int n=sizeof(A)/sizeof(int);
Print(A,n);
Print(B,n);
printf("%d\n",M_Search(A,B,n));
return 0;
}
int M_Search(int A[],int B[],int n)
{
//分别定义序列A和B的首位数、末位数和中位数
int s1=0,d1=n-1,m1;
int s2=0,d2=n-1,m2;
while(s1!=d1||s2!=d2)
{
m1=(s1+d1)/2;
m2=(s2+d2)/2;
if(A[m1]==B[m2])
{
return A[m1];//满足1)
}
if(A[m1]<B[m2])//满足2)
{
if((s1+d1)%2==0)//若元素的个数为奇数
{
s1=m1;//舍弃A中点以前的数
d2=m2;//舍弃B中点以后的数
}
else//若元素的个数为偶数
{
s1=m1+1;//舍弃A中点及以前的数
d2=m2;//舍弃B中点以后的数
}
}
else//满足条件3)
{
if((s1+d1)%2==0)//若元素的个数为奇数
{
d1=m1;//舍弃A中点以后的数
s2=m2;//舍弃B中点以前的数
}
else//若元素的个数为偶数
{
d1=m1;//舍弃A中点以后的数
s2=m2+1;//舍弃B中点及以前的数
}
}
}
return A[s1]<B[s2]?A[s1]:B[s2];
}
void Print(int A[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%-3d",A[i]);
printf("\n");
}
五、测试分析:
算法时间复杂度lg(n),空间复杂度1。