做题总结——中位数
题目
题意分析:
这道题目题意其实并不理解,相当于在插入数据的过程中动态求中位数,每当插入奇数个数据时就求这所有奇数个数据的中位数。
做题思路:
-
开始看见这道题目,最暴力的思路肯定就是每当插入奇数个数据时,就将这奇数个数据排序,从而能够求得中位数(但可想而知这样的做法肯定会超时)。自己还是什么都不会,也没有什么思路,后来通过大神的分析发现其实这道题目有许多种不同的做法,利用了不同的数据结构。 -
这里自己使用的方法是堆的思想,建立一个大顶堆和一个小顶堆,mid代表比较变量(开始时是第一个数据元素,后面会进行更新)。如果插入的元素小于mid,则将该元素插入到大顶堆中,否则将该元素插入到小顶堆中,根据大顶堆、小顶堆各自的性质可以知道,大顶堆中的每一个元素都小于小顶堆中的元素。每当插入奇数个元素时,判断大顶堆中的元素个数与小顶堆中的元素个数是否相等(这是因为对于奇数个数据,大于中位数的元素个数=小于中位数的元素个数),如果大顶堆中的元素个数多于小顶堆,则将mid压入小顶堆,大顶堆中根结点的元素成为新的mid,重复该过程直至两个堆中元素个数相等;反之,如果如果小顶堆中的元素个数多于大顶堆,则将mid压入大顶堆,小顶堆中根结点的元素成为新的mid,重复该过程直至两个堆中元素个数相等,最后得到的mid就是所求的中位数。
代码实现
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,a[200000],mid;
cin>>n;
//利用优先队列实现堆的结构
priority_queue<int,vector<int>,less<int> > lar; //建立一个大根堆
priority_queue<int,vector<int>,greater<int> > sma; //建立一个小根堆
cin>>a[1];
mid=a[1]; //开始时mid时第一个数据元素
cout<<a[1]<<endl;
for(int i=2;i<=n;i++)
{
cin>>a[i];
if(a[i]>mid)
{
sma.push(a[i]);
}
else
{
lar.push(a[i]);
}
if(i&1) //看网上的代码看到一位大神这样写的,其实相当于判断i是否是奇数
{
while(sma.size()!=lar.size()) //当两个堆的元素个数不相等时
{
if(sma.size()>lar.size())
{
lar.push(mid);
mid=sma.top();
sma.pop();
}
else
{
sma.push(mid);
mid=lar.top();
lar.pop();
}
}
cout<<mid<<endl;
}
}
return 0;
}
```**加粗样式**