作者是大四软工的,在校备考研。听闻蓝桥杯校内选拔赛选上了学院就报销报名费,就去试个水。
赛后感觉中位数几何这道题很有意思,就挑出来讲讲。
题目
7-3 中位数几何
分数 12
作者 龚雄兴
单位 湖北文理学院
N个整数的中位数是指这N个整数排序后中间的那个数(即小于它和大于它的数的数量相等),如果个数为奇数,排序后中间的那个数即为中位数,并约定:如果N为偶数,则取排序后正中间的两个数的平均值(取整数)。编写程序,输出给定整数数组的前1个,前2个,……前N个的中位数(以空格分隔)。
输入格式:
第一行是整数的个数N(正整数)、第二行是空格间隔的N个整数。
输出格式:
花括号中的N个整数,以逗号分隔,依次是前一个,前两个,……前N个数的中位数(整数)。
输入样例:
6
-20 30 -10 10 40 -40
输出样例:
{-20,5,-10,0,10,0}
代码长度限制
16 KB简体中文
时间限制
40 ms40毫秒
内存限制
64 MB
思路
使用插入排序,因为每次循环中只有一个元素的位置需要调整
set集合直接拿下(其实不行,如果有重复的数据会自动删掉)
参考代码(c++) 插入排序写法
#include<bits/stdc++.h>
using namespace std;
//插入排序
void insert_sort(int a[],int n)
{
int j;
for(int i=1;i<n;i++){
int temp=a[i];
for(j=i-1;j>=0&&a[j]>temp;j--){
a[j+1]=a[j];
}
a[j+1]=temp;
}
}
int main()
{
int n;
cin>>n;
int a[n];
int b[n];
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
// 插入排序
insert_sort(a,i+1);
// 计算中位数
if(i%2==1){
b[i]=(a[i/2]+a[i/2+1])/2;
}else{
b[i]=a[i/2];
}
}
cout<<"{";
for(int i=0;i<n;i++){
cout<<b[i];
if(i!=n-1){
cout<<",";
}
}
cout<<"}";
return 0;
}
思考过程
选拔赛时用快排只能过一大半案例,实在想不出怎么优化就放弃了,之后几天思考如何降低时间复杂度。原先写法是一个循环套sort()函数,时间复杂度n*nlogn=n^2logn,按理说快排已经算是排序算法中时间复杂度最低的了。
除非,没有必要无脑用快排。仔细研究题目,题目要求每一次都要输出前N个的中位数,即每次都需要对前N个数排序以便找出中位数。这其实并不需要用上快排。
因为每一次循环都需要有序的前N个数。即第N次循环时需要有序的前N个数,而上一次循环已经对前N-1个数排序好了,而这第N个数这一个数只需插入排序(遍历一次)就可以排序完成。对于这种情况来说,插入排序要比快速排序更好。
简单写了下插入排序的函数,过了!
参考代码(c++) set写法(下面是错的,不要参考)
//#include <bits/stdc++.h>
//using namespace std;
//set<int>s;
//
//int main() {
// int n, a;
// cin >> n;
// cout << "{";
// for (int i = 0; i < n; i++) {
// cin >> a;
// s.insert(a);
// set<int>::iterator it;
// it = s.begin();
计算中位数
// int c = i / 2;
// while (c--)
// it++;
// if (i % 2 == 1)
// cout << (*it++ + *it) / 2;
// else
// cout << *it;
// if (i != n - 1)
// cout << ",";
// }
// cout << "}";
// return 0;
//}