• 支线任务8-Find Median from Data Stream(中位数问题)


    一、题目描述

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

    Examples: 

    [2,3,4] , the median is 3

    [2,3], the median is (2 + 3) / 2 = 2.5

    Design a data structure that supports the following two operations:

    • void addNum(int num) - Add a integer number from the data stream to the data structure.
    • double findMedian() - Return the median of all elements so far.

    For example:

    add(1)

    add(2)

    findMedian() -> 1.5

    add(3) 

    findMedian() -> 2

    二、解题思路

      一开始当我发现这个题目是一个求中位数的问题之后 ,我并没有觉得这个题十分的困难,理论上只要将数据排序然后找出中间的数即可。但是我猛然发现难度标识为hard并且通过率只有19%左右,我就觉得此中必有玄机。

      后来我经过分析之后认为,这个题主要考察的可能是数据的处理速度。毕竟有了上次天际线问题以及最大矩形面积问题都是写了一个平庸的算法之后超时的经验,我这次预先对数据结构进行了一些调查。后来发现,向量数组应该是一种能够较快的完成寻找中位数功能的数据结构 ,毕竟向量本质上是一个动态链表,插入数据的速度较快,而题目中要求的函数又正是使用插入的方式扩充数据容量的。因此只需要定位好插入的位置即可。

      至于输出中位数,使用向量则更加简单,首位相加折半即可得到中位数的位置。

      由此,我决定使用向量作为存储数据的结构 。

      关于插入位置的定位问题,我经过研究,觉得二分法是在输入变量随机的情况下最快的一种可能查找方式了,于是我就写了一个二分法查询定位加上以向量为数据结构的算法。输出是平凡的找出中位数的值即可(十分简单)。

      最后经测试算法正确有效,并且运行速度较快,超过了70%以上的提交结果,应该说是一个较为有效率的算法。

    三、源代码部分

     1 #include <iostream>
     2 using namespace std;
     3 #include <vector>
     4 
     5 
     6 class MedianFinder {
     7 public:
     8 
     9 // Adds a number into the data structure.
    10 void addNum(int num) {
    11 if(this->array.size() == 0) this->array.push_back(num);
    12 else{
    13 int low = 0;
    14 int high = this->array.size() - 1;
    15 int mid;
    16 while(low <= high){
    17 mid = (low + high)/2;
    18 if(this->array[mid] == num) {
    19 this->array.insert(this->array.begin()+mid,num);
    20 return;
    21 }
    22 else if(this->array[mid] < num) low = mid + 1;
    23 else if(this->array[mid] > num)    high = mid - 1;
    24 }
    25 if(low >= high) this->array.insert(this->array.begin() + low,num);
    26 }
    27 }
    28 
    29 // Returns the median of current data stream
    30 double findMedian() {
    31 if(this->array.size() % 2 == 1)
    32 return (double)this->array[this->array.size()/2];
    33 else if(this->array.size() % 2 == 0)
    34 return ((double)this->array[this->array.size()/2] + 
    35 (double)this->array[this->array.size()/2 - 1])/2;
    36 }
    37 private:
    38 vector<int> array;
    39 };

    四、总结

      这次任务应该说让我对查找以及数据处理的效率等问题有了更好的理解,在处理大规模数据时,一个有效率的算法的重要性变得更加的重要,这次实验也是一个十分有益的体验。后来发现堆也是一种行之有效的结构,不过我比较了一下发现几种用堆的算法好像都没有我的速度快,也就没有再写一个新的算法了。

     

  • 相关阅读:
    Rhythmk 一步一步学 JAVA(4):Spring3 MVC 之 Hello Word
    使用webclient同时post普通表单字段和文件表单字段数据到指定的URL【转】
    Rhythmk 一步一步学 JAVA(2) : 操作 MYSQL 数据库
    判断FLASH版本问题
    Rhythmk 一步一步学 JAVA(3): java JSON 数据序列化 以及反序列化
    Rhythmk 一步一步学 JAVA(5) Hibernate环境配置
    JS 数据存储
    文件下载 获取远程图片
    SQL SERVER 学习笔记
    AngularJS源码学习一 :directive
  • 原文地址:https://www.cnblogs.com/czy-skyline/p/5081016.html
Copyright © 2020-2023  润新知