CD 80 随时找到数据的中位数

这篇博客介绍了一个用两个优先队列(大顶堆和小顶堆)实现的数据结构MedianHolder,该结构能够在线性时间内插入新数,并在常数时间内获取数据流的中位数。博主通过示例详细解释了算法的工作原理和操作流程,并展示了如何处理边界情况,例如数据流为空时的查询。此外,还提供了C++代码实现作为参考。
摘要由CSDN通过智能技术生成

题目描述
有一个源源不断的吐出整数的数据流,假设你有足够的空间来保存吐出的数。请设计一个名叫MedianHolder的结构,MedianHolder可以随时取得之前吐出所有数的中位数。
[要求]

  1. 如果MedianHolder已经保存了吐出的N个数,那么将一个新数加入到MedianHolder的过程,其时间复杂度是O(logN)。
  2. 取得已经吐出的N个数整体的中位数的过程,时间复杂度为O(1)
    输入描述:
    第一行一个整数Q,表示有Q次询问。
    接下来Q行,每行有一个整数opt表示操作类型
    若opt=1,则接下来有一个整数N表示将N加入到结构中。
    若opt=2,则表示询问当前所有数的中位数
    输出描述:
    输出若干行,每行一个浮点数数表示该次询问的答案(保留至小数点后一位)
    若询问时数据流中没有数输出-1(不需要输出小数点后的数字)
    具体输出要求请看样例
    示例1
    输入
    复制
    8
    1 5
    2
    1 3
    2
    1 6
    2
    1 7
    2
    输出
    复制
    5.0
    4.0
    5.0
    5.5
    说明
    第一次查询时结构内的数为:5
    第二次查询时结构内的数为:3 5
    第二次查询时结构内的数为:3 5 6
    第二次查询时结构内的数为:3 5 6 7
    示例2
    输入
    复制
    3
    2
    1 1
    2
    输出
    复制
    -1
    1.0

注意:在STL中使用v.size()-v1.size()如果结果为负数,那么会得到一个很大的正数。

#include<iostream>
#include<queue>
using namespace std;

priority_queue<int> big_q;//堆顶元素更大  ,这里储存较小元素 
priority_queue<int,vector<int>,greater<int> > small_q;//堆顶元素更小 

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		int x;
		scanf("%d",&x);
		if(x==1)
		{
			int y;
			scanf("%d",&y);
			if( big_q.empty() || y<big_q.top() )
			   big_q.push(y);
			else
			   small_q.push(y);
			//调整大,小根堆的元素个数 ,使其相差<1
			int len1=big_q.size(),len2=small_q.size();
			if(len1 - len2 >1 )
			{
				int x=big_q.top();
				big_q.pop();
				small_q.push(x);
			} 
			else if( len2-len1 >1  )// 并且stl模板库中的size()函数相减如果时一个负数那么得到的都是一个很大的整数   v1.size()-v2.size(); 
			{
				int x=small_q.top();
				small_q.pop();
				big_q.push(x);
			}
		 

		}
		else  //查询当前的中位数 
		{
			if( big_q.empty() )
			cout<<-1<<endl;
			else if( big_q.size()==small_q.size() )
			{
				printf("%.1f\n", 0.5*(big_q.top()+small_q.top() ) );
			}
			else
			{
				printf("%.1f\n", big_q.size()>small_q.size() ? 1.0*big_q.top() : 1.0*small_q.top()   );
			}
		}
	}
 
	 
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值