【剑指offer】数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
分析:大根堆小根堆法
现在假设数组有序,如果我们把数组的前半部分放入一个大根堆,数组的后半部分放入一个小根堆,那么中位数就只能是大根堆的堆顶元素和小根堆的堆顶元素,或者二者堆顶元素的平均值
我们在插入的时候只有遵循某种规则,就能达到这种效果
插入的时候两个堆的元素数量不同,则将新元素插入数量少的堆
若元素数量相同,则随便插入一个堆
若大根堆的堆顶元素大于小根堆的堆顶元素,则交换其堆顶元素
插入完成后,根据元素的数量来确定中位数的值
时间复杂度:插入一个数O(N*log N),获取中位数O(1)
class Solution { public: priority_queue<int,vector<int>,less<int> > q1; //大根堆 priority_queue<int,vector<int>,greater<int> > q2; //小根堆 //插入数 void Insert(int um) { int x=um; //插入规则 if(q1.size()==q2.size()) { q2.push(x); } else if(q2.size()>q1.size()) { q1.push(x); } else if(q1.size()>q2.size()) { q2.push(x); } //根据大根堆小根堆堆顶元素的关系判断是否交换堆顶元素, //保证堆中的数据是正确的 //(即大根堆保存有序数组前半部分的元素,小根堆保存有序数组后半部分的元素) if(q1.size()!=0&&q2.size()!=0) { if(q1.top()>q2.top()) { int a=q1.top(); int b=q2.top(); q1.pop(); q2.pop(); q1.push(b); q2.push(a); } } } double GetMedian() { double x; //根据元素的数量奇偶和元素的分布来求中位数 if(q1.size()==q2.size()) { x=(q1.top()*1.0+q2.top()*1.0)/2.0; } else if(q2.size()>q1.size()) { x=q2.top()*1.0; } else if(q1.size()>q2.size()) { x=q1.top()*1.0; } return x; } };
心之所向,素履以往
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南