zoukankan      html  css  js  c++  java
  • 解题报告:LeetCode Find Median from Data Stream(查找中位数)

    题目来源: https://leetcode.com/problems/find-median-from-data-stream/

    题目描述:实现一个能插入数据和查询当前中位数的数据结构。

    输入输出:输入输出格式请查看题目链接。

    解题思路

    1,首先,一个很简单粗暴的想法是直接用vector储存数据并在每次查询时调用algorithm库中的sort函数进行排序,然后输出可直接输出中间值或中间值的平均数作为中位数。代码如下:

    class MedianFinder {
    public:
        std::vector<int> numbers;
    
        MedianFinder():sum(0),n(0){};
    
        // Adds a number into the data structure.
        void addNum(int num) {
           numbers.push_back(num);
        }
    
        // Returns the median of current data stream
        double findMedian() {
            int n = numbers.size();
            sort(&(numbers[0]), &(numbers.back());
            return (numbers[n/2]+numbers[(n-1)/2])/2;
        }
    };
    View Code

    2,不出意外,这段代码超时了,于是我们需要优化一下。一个很自然的想法是仍然使用vector存储数据,每次插入之后直接进行插入排序即可。代码如下:

    const int maxn = 100000;
    class MedianFinder {
    public:
        int numbers[maxn];
        int n;
    
        MedianFinder():n(0){};
    
        // Adds a number into the data structure.
        void addNum(int num) {
            int pos = n-1;
            n ++;
            while(pos >= 0 && numbers[pos] > num)
            {
                numbers[pos+1] = numbers[pos];
                pos --;
            }
            numbers[pos+1] = num;
        }
    
        // Returns the median of current data stream
        double findMedian() {
             return (numbers[n/2]+numbers[(n-1)/2])/(double)2;
        }
    };
    View Code

    为了避免频繁的插入导致vector重新分配空间,上述代码使用了一个静态数组以解决这个问题。这段代码虽然很简单,但是出乎意料的是它AC了。虽然时间比较长。

    3,问题解决了之后,我将上述代码改为用vector存储数据,结果果断超时。再加上上述代码复杂度稍高,于是决定想出一种比较快速的方法。仔细回想这道题的要求,我们需要在插入后对数据进行排序,但是自己写的插入排序复杂度还是稍微高了一点,于是我们可以想到stl里面的很多的有自带排序的模板类,如set,priority_queue等。此外,我们只需要关心数据中的中间一个或两个元素。一种比较简单的办法是将输入数据分为两部分,一部分储存不大于中位数的数,一部分储存不小于中位数的数,且动态维持两部分中的数据规模不大于一即可。顺着这个思路,我们可以写出如下的代码(如下代码中使用了priority_queue作为容器来储存数据,且left队列中使用了系统自带的less比较模板类,以实现数据从小到大排序,right数组中使用了自定义的compare类,以实现数据从大到小的排序。):

     1   struct compare  
     2  {  
     3    bool operator()(const int& l, const int& r)  
     4    {  
     5        return l > r;  
     6    }  
     7  };  
     8 class MedianFinder {
     9 public:
    10     priority_queue<int, vector<int>, less<int>> left;
    11     priority_queue<int, vector<int>, compare> right;
    12 
    13     // Adds a number into the data structure.
    14     void addNum(int num) {
    15         if(left.size() == right.size())
    16         {
    17             if(right.size() && num > right.top())
    18             {
    19                 int num_temp = right.top();
    20                 right.pop();
    21                 right.push(num);
    22                 left.push(num_temp);
    23             }
    24             else
    25                 left.push(num);
    26         }
    27         else
    28         {
    29             if(num < left.top())
    30             {
    31                 int num_temp = left.top();
    32                 left.pop();
    33                 left.push(num);
    34                 right.push(num_temp);
    35             }
    36             else
    37                 right.push(num);
    38         }
    39 
    40     }
    41 
    42     // Returns the median of current data stream
    43     double findMedian() {
    44          return (left.size()==right.size() ? (left.top()+right.top())/double(2) : left.top());
    45     }
    46 };
    View Code
    此博客中的内容均为原创或来自网络,不用做任何商业用途。欢迎与我交流学习,我的邮箱是b-liu14@mails.tsinghua.edu.cn
  • 相关阅读:
    HDFS文件系统简单的Java读写操作
    HDFS文件读写流程简单图解
    大数据入门---------------------Java部分开始
    Hive 基础入门
    安卓 2.3 安装及环境搭建
    字节流与字符流的区别详解(转)
    Java File 类的使用方法详解(转)
    ThinkPHP Session 使用
    PHP TP框架
    对象和数组的相互转化
  • 原文地址:https://www.cnblogs.com/bill-liu/p/5068046.html
Copyright © 2011-2022 走看看