问题描述
有两个排序的数组,长度都为n,求合并后的排序数组的中位数.
直接遍历法,时间复杂度为O(n)
算法思想: 因为两个数组的长度都为n,那么合并后的中位数一定有两个,那么,我们只要在两个数组合并后的数组中找到找到第n个和第n-1个元素加起来除2就能得到其中位数。 (当然,我们不会真正的去合并两个数组).
#include<iostream>
#include<iomanip>
using namespace std;
double getmedian(int *a,int *b,int n)
{
int count=0;
int i=0,j=0;
double mid;
while(count < n-1){ //循环找到合并后中间的两个中位数在两个数组中对应的下标.
if(a[i]<b[j]){
i++;
count++;
}else{
j++;
count++;
}
}
return (a[i]+b[i])/2.0;
}
int main(int argc,char *argv[])
{
int a[]={1,2,3,4,5};
int b[]={6,7,8,9,10};
double c=getmedian(a,b,5);
cout << "中位数是:"<<c<<endl;
return 0;
}
分治法,时间复杂度为O(log(m+n))
假设A数组的中位数为m1,数组B的中位数为m2,例如:
a[]={1,5,6,9,10};
b[]={2,4,7,12,23};
m1=6,m2=7,由于m1
#include<iostream>
using namespace std;
int median(int *p,int n)
{
if(n%2==0){
return (p[n/2]+p[n/2-1])/2; //当其元素个数为偶数时,找其下中位数和上中位数和的一半。
}else{
return p[n/2];
}
}
double find_medin(int *a,int *b,int n)
{
double m1,m2;
if(n<=0){
return -1;
}
if(n==1){
return (a[0]+b[0])/2; //这代表a和b数组中各有1个元素,所以,直接相加除以2;
}
if(n==2){
return (max(a[0],b[0])+min(a[1],b[1]))/2; //当a和b中各有2个元素时,找出合并后中间两个数再除于2
}
m1=median(a,n);
m2=median(b,n);
if(m1==m2){ //相等就是中位数.
return m1;
}
if(m1 < m2){
if(n%2==0)
return find_medin(a+n/2-1,b,n/2+1);
else
return find_medin(a+n/2,b,n/2+1);
}else{
if(n%2==0)
return find_medin(b+n/2-1,a,n/2+1);
else
return find_medin(b+n/2,a,n/2+1);
}
}
int main(int argc,char *argv[])
{
int a[]={1,12,10,26,38};
int b[]={2,13,17,30,45};
int n1=sizeof(a)/sizeof(a[0]);
int n2=sizeof(b)/sizeof(b[0]);
if(n1==n2){
cout << "Medin is "<<find_medin(a,b,n1);
}else{
cout <<"array input errno"<<endl;
}
return 0;
}