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