zoukankan      html  css  js  c++  java
  • 《剑指offer》第四十一题(数据流中的中位数)

    // 面试题41:数据流中的中位数
    // 题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么
    // 中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,
    // 那么中位数就是所有数值排序之后中间两个数的平均值。
    
    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    
    using namespace std;
    
    template<typename T> class DynamicArray
    {
    public:
        void Insert(T num)
        {
            if (((min.size() + max.size()) & 1) == 0)//没插入前判断当前总个数是奇还是偶,偶时插入最小堆
            {
                if (max.size() > 0 && num < max[0])//若该值属于最大堆
                {
                    max.push_back(num);//则先插入最大堆
                    push_heap(max.begin(), max.end(), less<T>());//使最后一个元素插到合适位置,符合最大堆规则
    
                    num = max[0];//令num等于最大堆里的最大值
    
                    pop_heap(max.begin(), max.end(), less<T>());//交换最大堆的最大值和最后一个值,弹出最大值,符合最大堆规则
                    max.pop_back();//删除最后一个元素,即刚才所述的最大值
                }
    
                min.push_back(num);//将num插入最小堆
                push_heap(min.begin(), min.end(), greater<T>());//使最后一个元素插到合适位置,符合最小堆规则
            }
            else//奇数插入最大堆,使大小堆保持平衡,下面代码同上
            {
                if (min.size() > 0 && min[0] < num)
                {
                    min.push_back(num);
                    push_heap(min.begin(), min.end(), greater<T>());
    
                    num = min[0];
    
                    pop_heap(min.begin(), min.end(), greater<T>());
                    min.pop_back();
                }
    
                max.push_back(num);
                push_heap(max.begin(), max.end(), less<T>());
            }
        }
    
        T GetMedian()
        {
            int size = min.size() + max.size();
            if (size == 0)
                throw exception("No numbers are available");
    
            T median = 0;
            if ((size & 1) == 1)
                median = min[0];//若总个数是奇数,则中值是最小堆的顶点
            else
                median = (min[0] + max[0]) / 2;//否则是最大堆和最小堆的顶点平均值
    
            return median;
        }
    
    private:
        vector<T> min;
        vector<T> max;
    };
    
    // ====================测试代码====================
    void Test(const char* testName, DynamicArray<double>& numbers, double expected)
    {
        if (testName != nullptr)
            printf("%s begins: ", testName);
    
        if (abs(numbers.GetMedian() - expected) < 0.0000001)
            printf("Passed.
    ");
        else
            printf("FAILED.
    ");
    }
    
    int main()
    {
        DynamicArray<double> numbers;
    
        printf("Test1 begins: ");
        try
        {
            numbers.GetMedian();
            printf("FAILED.
    ");
        }
        catch (const exception&)
        {
            printf("Passed.
    ");
        }
    
        numbers.Insert(5);
        Test("Test2", numbers, 5);
    
        numbers.Insert(2);
        Test("Test3", numbers, 3.5);
    
        numbers.Insert(3);
        Test("Test4", numbers, 3);
    
        numbers.Insert(4);
        Test("Test6", numbers, 3.5);
    
        numbers.Insert(1);
        Test("Test5", numbers, 3);
    
        numbers.Insert(6);
        Test("Test7", numbers, 3.5);
    
        numbers.Insert(7);
        Test("Test8", numbers, 4);
    
        numbers.Insert(0);
        Test("Test9", numbers, 3.5);
    
        numbers.Insert(8);
        Test("Test10", numbers, 4);
        system("pause");
        return 0;
    }
  • 相关阅读:
    RxJava学习经验谈——map与flatmap
    不要打断链式结构:使用 RxJava的 compose() 操作符
    Android Retrofit网络请求Service,@Path、@Query、@QueryMap、@Map...
    Android 勤用RXJava compose操作符消除重复代码
    Android使用token维持登陆状态的方法
    Java服务器对外提供接口以及Android端向服务器请求数据
    Retrofit请求数据对错误以及网络异常的处理
    Retrofit2.0+OkHttp打印Request URL(请求地址参数)
    HUE配置文件hue.ini 的hbase模块详解(图文详解)(分HA集群和非HA集群)
    安装Hue后的一些功能的问题解决干货总结(博主推荐)
  • 原文地址:https://www.cnblogs.com/CJT-blog/p/10520259.html
Copyright © 2011-2022 走看看