题解:学而思编程 动态中位数
【题目来源】
学而思编程:动态中位数
【题目描述】
依次读入一个整数序列,每当已经读入的整数个数为奇数时,输出已读入的整数构成的序列的中位数。
【输入】
第一行一个整数 \(N(1≤N≤105)\),表示序列长度。
第二行 \(N\) 个整数 \(A_i(1≤A_i≤10^9)\)
【输出】
输出 \(⌊\displaystyle\frac{N+1}{2}⌋\) 行(向下取整),第 \(i\) 行为 \(A_1\) 到 \(A_{2i−1}\) 的中位数。
【输入样例】
7
1 3 5 7 9 11 6
【输出样例】
1
3
5
6
【核心思想】
-
问题分析:依次读入 \(N\) 个整数,每当已读入的整数个数为奇数时,输出当前序列的中位数。这是一个动态中位数问题,需要在数据流中实时维护中位数。
-
算法选择:
- 双堆策略(大根堆 + 小根堆):使用两个优先队列(堆)来维护数据流
- 大根堆(small):存储较小的一半数字,堆顶为较小部分的最大值
- 小根堆(big):存储较大的一半数字,堆顶为较大部分的最小值
- 平衡维护:确保两个堆的大小差不超过 \(1\),且大根堆的大小始终大于等于小根堆
-
关键步骤:
- 初始化:创建大根堆
small和小根堆big - 插入元素(处理第 \(i\) 个元素 \(A_i\)):
- 如果
small非空且 $A_i > $small.top(),则将 \(A_i\) 放入big - 否则将 \(A_i\) 放入
small
- 如果
- 奇数时输出中位数(当 \(i\) 为奇数时):
- 调整堆大小:确保
small.size() = big.size() + 1 - 如果
small.size() < big.size(),将big.top()移到small - 中位数为
small.top(),输出
- 调整堆大小:确保
- 偶数时平衡堆(当 \(i\) 为偶数时):
- 调整堆大小:确保
small.size() = big.size() - 如果
small.size() < big.size(),将big.top()移到small - 如果
small.size() > big.size(),将small.top()移到big
- 调整堆大小:确保
- 初始化:创建大根堆
-
时间/空间复杂度:
- 时间复杂度:\(O(N \log N)\),每次插入和堆调整操作均为 \(O(\log N)\),共 \(N\) 次操作
- 空间复杂度:\(O(N)\),需要存储所有 \(N\) 个元素在两个堆中
-
双堆维护中位数的核心思想:
- 数据分流:根据当前元素与堆顶的比较,决定放入哪个堆,保持有序性
- 大小平衡:通过控制两个堆的大小关系,确保中位数始终在大根堆的堆顶
- 动态调整:每次插入后根据奇偶性调整堆的大小,保证中位数的正确性
- 中位数定位:当元素总数为奇数时,中位数是较大一半的最小值(大根堆顶)
- 适用于数据流中位数查询、动态序列统计类问题
【算法标签】
堆排序
【代码详解】
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
// 小根堆存储较大的一半数字
priority_queue<int> small;
// 大根堆存储较小的一半数字
priority_queue<int, vector<int>, greater<int>> big;
int n, a;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a;
// 根据当前数字与small堆顶比较,决定放入哪个堆
if (!small.empty() && a > small.top())
{
big.push(a);
}
else
{
small.push(a);
}
// 当i为奇数时,输出中位数
if (i % 2)
{
// 调整两个堆的大小,确保small堆的大小比big堆大1
if (small.size() < big.size())
{
small.push(big.top());
big.pop();
}
cout << small.top() << endl; // 中位数是small堆的堆顶
}
else
{
// 当i为偶数时,平衡两个堆的大小
if (small.size() < big.size())
{
small.push(big.top());
big.pop();
}
else if (small.size() > big.size())
{
big.push(small.top());
small.pop();
}
}
}
return 0;
}
【运行结果】
7
1 3 5 7 9 11 6
1
3
5
6
浙公网安备 33010602011771号