B 朴素的中位数
时间限制:1000ms 内存限制:65536kb
题目描述
两个有序数组num1和num2,均是从小到大排列,长度分别为n和m。找出这两个数组的中位数。
输入
两个整数n,m,分别为数组num1和num2的长度(0<=n,m<=1000000)
接下来n个数为num1中的整数。
然后m个数为num2中的整数。
输出
对于每组数据,输出两个数组的中位数。偶数情况下输出中间两个数的平均数。均保留小数点后一位。若两个数组均为空,输出0.0。
输入样例
2 1
1 3
2
2 2
1 2
3 4
输出样例
2.0
2.5
HINT
如果wa的很奇怪,那可能是……数据会超过int范围
题目分析
首先,本题要声明三个大容量的数组,为了避免出现内存方面的问题,应该声明在函数外面。
然后,我们开始分析这个题目,对于给定的这两个数组num1、num2,它们各自都是从小到大排列好的,这就需要我们换一种思路去找中位数,而不是将两个数组再重新组合排序了。
一组排好序的数据的中位数,一定是出现在这组数据的中间位置的,我们只要找到位于该位置处的数据即可。
我们可以设置一个储存数据的数组a,然后从num1、num2数组的初始位置开始,依次把较小的数据存入数组a中,并记录好a中已有数据的个数k,直到k等于(n+m)/
2(n+m为偶数)或(n+m-1)/2(n+m为奇数)。
示例代码
#include<cstdio>
long long num1[1000008],num2[1000007],a[2000001];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%lld",&num1[i]);
}
for(int i=0; i<m; i++)
{
scanf("%lld",&num2[i]);
}
if(n==0&&m==0)
{
printf("0.0\n");
}
else
{
int i=0,j=0;
int k;
if((n+m)%2==0)
k=(n+m)/2;
else
k=(n+m-1)/2;
for(int t=0; t<=k; t++)
{
if(i==n)
{
a[t]=num2[j];
if(j<m)
j++;
}
else if(j==m)
{
a[t]=num1[i];
if(i<n)
i++;
}
else if(num1[i]<num2[j])
{
a[t]=num1[i];
if(i<n)
i++;
}
else
{
a[t]=num2[j];
if(j<m)
j++;
}
}
if((n+m)%2==0)
{
double o1=a[(n+m)/2],o2=a[(n+m)/2-1];
double ans=(o1+o2)/2;
printf("%.1lf\n",ans);
}
else
{
double ans2;
ans2=a[(n+m-1)/2];
printf("%.1lf\n",ans2);
}
}
}
}
#include<cstdio>
long long num1[1000008],num2[1000007],a[2000001];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%lld",&num1[i]);
}
for(int i=0; i<m; i++)
{
scanf("%lld",&num2[i]);
}
if(n==0&&m==0)
{
printf("0.0\n");
}
else
{
int i=0,j=0;
int k;
if((n+m)%2==0)
k=(n+m)/2;
else
k=(n+m-1)/2;
for(int t=0; t<=k; t++)
{
if(i==n)
{
a[t]=num2[j];
if(j<m)
j++;
}
else if(j==m)
{
a[t]=num1[i];
if(i<n)
i++;
}
else if(num1[i]<num2[j])
{
a[t]=num1[i];
if(i<n)
i++;
}
else
{
a[t]=num2[j];
if(j<m)
j++;
}
}
if((n+m)%2==0)
{
double o1=a[(n+m)/2],o2=a[(n+m)/2-1];
double ans=(o1+o2)/2;
printf("%.1lf\n",ans);
}
else
{
double ans2;
ans2=a[(n+m-1)/2];
printf("%.1lf\n",ans2);
}
}
}
}