本题要求实现一个函数,求N个集合元素A[]的中位数,即序列中第⌊(N+1)/2⌋大的元素。其中集合元素的类型为自定义的ElementType。
函数接口定义:
ElementType Median( ElementType A[], int N );
其中给定集合元素存放在数组A[]中,正整数N是数组元素个数。该函数须返回N个A[]元素的中位数,其值也必须是ElementType类型。
裁判测试程序样例:
#include <stdio.h>
#define MAXN 10
typedef float ElementType;
ElementType Median( ElementType A[], int N );
int main ()
{
ElementType A[MAXN];
int N, i;
scanf("%d", &N);
for ( i=0; i<N; i++ )
scanf("%f", &A[i]);
printf("%.2f\n", Median(A, N));
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
3
12.3 34 -5
输出样例:
12.30
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
题解
基于快排思想,前面一直在“偶数个”以及“超过10,中位数是第1个”卡了很久,搞半天题目写着第【(N+1)/2向下取整】大的元素,而我一直从小到大排序的。然后针对超时被卡,至于要将排序全部数字改为每次只排可能存在中位数的一部分即可。
以下是我自己写的,好像和快排不太一样,直接在partition里递归了,不过能通过。
int partition( ElementType A[],int start,int end,int N){
//printf("partition%d~%d\n",start,end);
if(start>=end) return start;
int x=start,y=end;
ElementType stand=A[start];
//printf("stand=%f\n",stand);
while(x<y){
while(x<y && A[y]<stand){y--;}
A[x]=A[y];//printf("change%fand%f\n",A[x],A[y]);
while(x<y && A[x]>=stand){x++;}
A[y]=A[x];//printf("change%fand%f\n",A[y],A[x]);
}
A[x]=stand;
if(x==((N+1)/2-1)) return x;
else if(x>(N+1)/2-1)partition(A,start,x-1,N);
else partition(A,x+1,end,N);
}
ElementType Median( ElementType A[], int N ){
int x=partition(A,0,N-1,N);
/* for(int i=0;i<N;i++){
printf("%.2f ",A[i]);
}
printf("\n"); */
x=(N+1)/2-1;
return A[x];
}
以下是chatGPT改后
int partition(ElementType A[], int low, int high, int medianPos) {
ElementType pivot = A[low];
int start = low, end = high;
while (start < end) {
while (start < end && A[end] <= pivot) end--;
A[start] = A[end];
while (start < end && A[start] >= pivot) start++;
A[end] = A[start];
}
A[start] = pivot;
return start;
}
ElementType Median(ElementType A[], int N) {
int low = 0, high = N - 1, medianPos = (N - 1) / 2;
int pos = -1;
while (pos != medianPos) {
pos = partition(A, low, high, medianPos);
if (pos < medianPos) low = pos + 1;
else if (pos > medianPos) high = pos - 1;
}
return A[medianPos];
}