求一个无序数组的中位数。

问题描述

求一个无序数组的中位数。
如:{2,5,4,9,3,6,8,7,1}的中位数为5,{2,5,4,9,3,6,8,7,1,0}的中位数为4和5。

要求:不能使用排序,时间复杂度尽可能低。

提示:考虑堆或者快排思想解决

方法1:堆

思路1:
分析:将数据平均分配到最大堆和最小堆中,并且保证最小堆中的数据存放的数据都比最大堆中是数据大,那么此时最小堆堆顶的元素一定是中位数。
那么如何保证最小堆中的元素,都比大堆中的元素大。

(1)遍历数组,将第i个数插入堆中,i为奇数时,插入最小堆,i为偶数时插入最大堆。(最大堆的插入的数据比较大)
(2)每次插入时,将最大堆和最小堆的堆顶交换

void GetMid(int arr[],int size)
{
    priority_queue<int> max_heap;
    priority_queue< int, vector<int>, greater<int> > min_heap;

    for (int i = 0; i < size; ++i)
    {
        //i是从0开始的,所以max存放的数据比较多
        if ((i & 1) == 1)
            min_heap.push(arr[i]);
        else
            max_heap.push(arr[i]);

        
### 使用最大堆和最小堆寻找无序数组中位数 为了高效地找到无序数组中的中位数及其原始下标,可以采用最大堆和最小堆相结合的方法。这种方法能够在O(log n)时间内完成插入操作,并保持数据结构平衡以便随时获取当前的中位数值。 具体实现如下: 1. 创建两个优先队列:一个是大根堆用于存储较小的一半元素;另一个是小根堆用来保存较大的一半元素。 2. 当新加入一个元素时,如果这个值小于等于大根堆顶,则将其放入大根堆;反之则进入小根堆。 3. 维护这两个堆之间的大小关系使得它们要么相等,要么大根堆多出一个小于等于小根堆顶部的那个唯一额外项。 4. 如果总数量为奇数,则中位数就是大根堆顶端元素;如果是偶数的话,那么中位数将是两者顶端元素平均值得到的结果[^1]。 然而上述方法并不能直接给出原数组里的索引位置。对于这个问题,可以在向堆里添加元素的同时维护一个哈希表来追踪每个值对应的初始索引。这样,在最终确定中位数后就可以通过查表得到其原本所在的位置了。 另外一种更简单但效率稍低的办法是先复制一份输入列表并对其进行排序处理,再依据定义从中选出位于中央处的目标数字,最后回到未排序版本的数据集中定位该目标的具体地址[^2]。 下面是基于Python语言的一个简易示例程序展示如何利用快速排序思想配合映射机制获得所需结果: ```python def find_median_index(arr): import copy # 复制数组以防修改原有数据 sorted_arr = copy.deepcopy(arr) # 对副本执行排序 sorted_arr.sort() length = len(sorted_arr) median_value = (sorted_arr[length // 2] + sorted_arr[(length - 1) // 2]) / 2 index_map = {value: idx for idx, value in enumerate(arr)} try: result_idx = index_map[median_value] except KeyError as e: # 若不存在确切匹配的情况(例如浮点型中位数) lower_bound = min(index_map.keys(), key=lambda k: abs(k-median_value)) result_idx = index_map[lower_bound] return result_idx test_array = [7, 9, 3, 5, 1] print(f"The original array is :{test_array}") result = find_median_index(test_array) print(f"Median element's original position was at index:{result}.") ``` 此代码片段展示了如何创建一个新的已排序序列以识别其中心值,并借助字典对象建立从值到原来索引间的对应关系,从而能够返回所中位数最初所在的下标位置[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值