POJ3784 Running Median(对顶堆动态求中位数)

 题目链接:http://exam.upc.edu.cn/problem.php?cid=1430&pid=15

题意:

给定数列a[1-n],起初有a[1]。每次输入两个数,输出当前数组的中位数

思路:

利用对顶堆求中位数,每次将输入的两个数分别插入最小堆和最大堆中,维护对顶堆,使最大堆的最大值(堆顶元素)小于最小堆的最小值(堆顶元素)。每次添加两个数后都可计算出此时的中位数——最大堆的堆顶元素。

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e4+5;

int n, m, temp[maxn], ans[maxn];
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        priority_queue<int,vector<int>,less<int> >a;
        priority_queue<int,vector<int>,greater<int> >b;
        scanf("%d%d", &m, &n);
        for(int i=1; i<=n; ++i) scanf("%d", &temp[i]);
        printf("%d %d\n", m, (n+1)/2);
        int cnt = 0;
        a.push(temp[1]); ans[++cnt]=temp[1];
        for(int i=2; i<=n; i+=2){
            b.push(temp[i]), a.push(temp[i+1]);
            while(a.top()>b.top()){
                int _a = a.top(), _b = b.top();
                a.pop(), b.pop();
                a.push(_b), b.push(_a);
            }
            ans[++cnt] = a.top();
        }
        int i;
        for(i=1; i<=cnt; ++i)
            printf("%d%c", ans[i], (i%10==0)?'\n':' ');
        if(i%10!=0) printf("\n");
    }
}

 

### 使用堆数据结构计算中位数 为了有效地使用堆来计算一组动态变化的数据流中的中位数,可以采用两个堆的组合方式:最大堆和最小堆。这种设计能够确保新加入的数据总能被放置到合适的位置,并保持整体平衡。 #### 数据结构的选择与维护 - **最大堆 (MaxHeap)** 存储较小的一半数值; - **最小堆 (MinHeap)** 存储较大的一半数值; 通过这种方式,在任何时刻: - 如果两堆大小相等,则当前中位数等于这两个堆顶元素平均值。 - 若某一侧多出一个元素,则该额外元素所在一侧即为当前中位数位置[^1]。 #### 插入操作逻辑 当有新的数值到来时,按照如下规则处理: 对于小于或等于`maxheap.top()`的新值应放入最大堆内;反之则进入最小堆。之后调整两者之间可能存在的不平衡状态——如果某个堆超出另一个超过一位以上,则需将其顶部元素移至另一方以恢复均衡。 ```python import heapq class MedianFinder: def __init__(self): self.max_heap = [] # stores the smaller half of numbers, inverted to use min heap as max heap self.min_heap = [] def addNum(self, num: int) -> None: if not self.max_heap or num <= -self.max_heap[0]: heapq.heappush(self.max_heap, -num) else: heapq.heappush(self.min_heap, num) # Balance heaps' sizes if len(self.max_heap) > len(self.min_heap) + 1: moved_num = -heapq.heappop(self.max_heap) heapq.heappush(self.min_heap, moved_num) elif len(self.min_heap) > len(self.max_heap): moved_num = heapq.heappop(self.min_heap) heapq.heappush(self.max_heap, -moved_num) def findMedian(self) -> float: if len(self.max_heap) == len(self.min_heap): return (-self.max_heap[0] + self.min_heap[0]) / 2 else: return -self.max_heap[0] ``` 此方法能够在O(log n)时间内完成每次插入操作,并能在常量时间复杂度下获取中位数,非常适合用于解决在线算法问题或是实时数据分析场景下的需
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值