题目:(寻找中位数)一个长度为L(L≥1)的升序序列S,处在第L/2(若为小数则去掉小数后加1)个位置的数称为S的中位数。例如,若序列S1=(11,13,15,17,19),则S1的中位数是15。两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1和S2的中位数是11。现有两个等长升序序列A和B,试实现一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。
代码码如下:
方法一:使用归并的思想,但不实现归并(其实就是查找),次优解但是写出来更省时,
//找两个升序序列的中位数
//方法1:使用归并的思想,但不实现归并(其实就是查找)
#include<stdio.h>
int seekmid(int A[],int B[],int n) //此算法可优化
{
while(1){
int i=0;
int j=0;
for(i=0;A[i]<B[j];i++)
{
if(i+j+2==2/n)
{
return A[i];
}
}
for(j=0;A[i]>=B[j];j++)
{
if(i+j+2==2/n)
{
return B[j];
}
}
}
}
void main(){
int a[5]={11,13,15,17,19};
int b[5]={2,4,8,12,20};
printf("%d%\n",seekmid(a,b,5));
}
方法二:最优解法(归并逆序(减治法))
//最优解法(归并逆序(减治法))
int seekmid(int A[],int b[],int n)
{
int s1,d1,m1,s2,d2,m2;
s1=0;di=n-1;
s2=0;d2=n-1;
while(s1!=d1||s2!=d1)
{
m1=(s1+d1)/2;
m2=(s2+d2)/2;
if(A[m1]==B[m2])
return A[m1];
if(A[m1]<B[m2])
{
if((s1+d1)%2==0)
{ //长度为奇数
s1=m1; //A的元素小,则保留A中大的元素
d2=m2; //B的元素大,则保留B中小的元素
}
else //长度为偶数
{
s1=s1+1;
d2=m2;
}
}
else
{ //(A[m1]>B[m2])
if((s1+d1)%2==0)
{ //长度为奇数
d1=m1; //A的元素大,则保留A中小的元素
s2=m2; //B的元素小,则保留B中大的元素
}
else{ //长度为偶数
d1=m1;
s2=s2+1;
}
}
}
return A[s1]<B[s2]? A[s1]:B[s2];//返回其中较小的既是最终答案
}
void main(){
int a[5]={11,13,15,17,19};
int b[5]={2,4,8,12,20};
printf("%d%\n",seekmid(a,b,5));
}
方法三:实现归并后找中位数
注:此方法能写出归并排序算法再查找n/2处寻找中位数即可。
图解算法最次优算法:
!!!!!太费时间简单搞一下!!!!!
最优解查找法简单图解