支線任務8-Find Median from Data Stream(中位數問題)

1、題目描述ios

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:this

add(1)spa

add(2)code

findMedian() -> 1.5blog

add(3) 

findMedian() -> 2

 

2、解題思路

  一開始當我發現這個題目是一個求中位數的問題以後 ,我並無以爲這個題十分的困難,理論上只要將數據排序而後找出中間的數便可。可是我猛然發現難度標識爲hard而且經過率只有19%左右,我就以爲此中必有玄機。

  後來我通過分析以後認爲,這個題主要考察的多是數據的處理速度。畢竟有了上次天際線問題以及最大矩形面積問題都是寫了一個平庸的算法以後超時的經驗,我此次預先對數據結構進行了一些調查。後來發現,向量數組應該是一種可以較快的完成尋找中位數功能的數據結構 ,畢竟向量本質上是一個動態鏈表,插入數據的速度較快,而題目中要求的函數又正是使用插入的方式擴充數據容量的。所以只須要定位好插入的位置便可。

  至於輸出中位數,使用向量則更加簡單,首位相加折半便可獲得中位數的位置。

  由此,我決定使用向量做爲存儲數據的結構 。

  關於插入位置的定位問題,我通過研究,以爲二分法是在輸入變量隨機的狀況下最快的一種可能查找方式了,因而我就寫了一個二分法查詢定位加上以向量爲數據結構的算法。輸出是平凡的找出中位數的值便可(十分簡單)。

  最後經測試算法正確有效,而且運行速度較快,超過了70%以上的提交結果,應該說是一個較爲有效率的算法。

 

3、源代碼部分

 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 };

 

4、總結

  此次任務應該說讓我對查找以及數據處理的效率等問題有了更好的理解,在處理大規模數據時,一個有效率的算法的重要性變得更加的重要,此次實驗也是一個十分有益的體驗。後來發現堆也是一種行之有效的結構,不過我比較了一下發現幾種用堆的算法好像都沒有個人速度快,也就沒有再寫一個新的算法了。

相關文章
相關標籤/搜索