每日一算法题-数据流中的中位数

112 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

一、题目

描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

image.png

#include <iostream>
using namespace std;

class YuanDad {
public:
    void Insert(int num) {
    }

    double GetMedian() {
    }
};


int main(int, char*[])
{
    YuanDad object;
    object.Insert(5);
    cout << "right: " << "5.0" << ",real: " << object.GetMedian() << endl;
    object.Insert(2);
    cout << "right: " << "3.5" << ",real: " << object.GetMedian() << endl;
    object.Insert(3);
    cout << "right: " << "3.0" << ",real: " << object.GetMedian() << endl;
    object.Insert(4);
    cout << "right: " << "3.5" << ",real: " << object.GetMedian() << endl;
    object.Insert(1);
    cout << "right: " << "3.0" << ",real: " << object.GetMedian() << endl;
    object.Insert(6);
    cout << "right: " << "3.5" << ",real: " << object.GetMedian() << endl;
    object.Insert(7);
    cout << "right: " << "4.0" << ",real: " << object.GetMedian() << endl;
    object.Insert(0);
    cout << "right: " << "3.5" << ",real: " << object.GetMedian() << endl;
    object.Insert(8);
    cout << "right: " << "4.0" << ",real: " << object.GetMedian() << endl;
}

二、分析

由题意可知,要获取数据流中的中位数,就离不开排序。
有序排序算法肯定离不开二分插入排序,但是这里我决定用另一种方法,更直观,更好的理解这道题解题的原理。
我们所要得到的结果是中位数,随意可以记录中间结点,然后直接对中间节点进行比较,拿值,因为不管是偶数还是奇数,我们都只需要关心中间的一个/两个数。

三、模拟

  1. 5
    中间节点: 5
    中位数:5
  2. 2, 5
    中间节点: 2和5的平均值
    中位数: 3.5
  3. 2, 3, 5
    中间节点: 3
    中位数: 3
  4. 2, 3, 4, 5
    中间节点: 3和4的平均值
    中位数: 3.5
  5. 1, 2, 3, 4, 5
    中间节点: 3
    中位数: 3
  6. 1, 2, 3, 4, 5, 6
    中间节点: 3和4的平均值
    中位数: 3.5
  7. 1, 2, 3, 4, 5, 6, 7
    中间节点: 4
    中位数: 4
  8. 0, 1, 2, 3, 4, 5, 6, 7
    中间节点: 3和4的平均值
    中位数: 3.5
  9. 0, 1, 2, 3, 4, 5, 6, 7, 8
    中间节点: 4
    中位数: 4

四、实现

class YuanDads {
public:
    struct QyList{
        explicit inline QyList(int val): val(val) {}
        void left(QyList* other){ if(pre) pre->next = other; other->pre = pre; pre = other; other->next = this;}
        void right(QyList* other){ if(next) next->pre = other; other->next = next; next = other; other->pre = this; }
        int val;
        QyList* pre = nullptr;
        QyList* next = nullptr;

    };
    QyList *min = nullptr, *max = nullptr, *median = nullptr;
    bool odd = false;
    void Insert(int num) {
        odd = !odd;
        QyList* node = new QyList(num);
        if(odd){
            if(median){
                if(num < min->val){
                    QyList* temp = min;
                    while(temp->pre && temp->pre->val > num) temp = temp->pre;
                    temp->left(node);
                    median = min;
                    min = min->pre;
                }else if(num > max->val){
                    QyList* temp = max;
                    while(temp->next && temp->next->val < num) temp = temp->next;
                    temp->right(node);
                    median = max;
                    max = max->next;
                }else{
                    median = node;
                    min->right(median);
                }
            }else{
                median = node;
            }
        }else{
            if(num < median->val){
                if(min){
                    QyList* temp = median;
                    while(temp->pre && temp->pre->val > num) temp = temp->pre;
                    temp->left(node);
                    max = median;
                    min = median->pre;
                }else{
                    min = node;
                    max = median;
                    max->left(min);
                }
            }else{
                if(min){
                    QyList* temp = median;
                    while(temp->next && temp->next->val < num) temp = temp->next;
                    temp->right(node);
                    min = median;
                    max = median->next;
                }else{
                    max = node;
                    min = median;
                    min->right(max);
                }
            }
        }
    }

    double GetMedian() {
        if(odd){
            return static_cast<double>(median->val);
        }else{
            return (min->val + max->val) / 2.0;
        }
    }

};

五、结言

理解为主

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!