面试题71:数据流中的中位数

来源:互联网 发布:房源软件哪个好 编辑:程序博客网 时间:2024/04/26 02:59

解法一:

先存数组,再排序(效率很低)

解法二:

先存数组,再冒泡排序排一半(效率同样很低)

解法三:(推荐)
先存数组,利用partition函数原理,如果partition返回的index刚好是数组长度的一半,那么这个index对应的数就是中位数啦。

时间复杂度:O(n)

#include<iostream>using namespace std;int Partition(int *arr, int start, int end)  //此处end为最后一个元素对应下标{if (start == end) return start;int pivot = arr[end];int first = start-1;   //始终指向分好部分最后一个小于pivot的元素for (int second = start; second < end; ++second){if (arr[second] < pivot){first++;    //让其指向第一个比pivot大的元素if(first!=second) swap(arr[first], arr[second]);}}++first;swap(arr[first], arr[end]);return first;}void QuickSort(int *arr, int start, int end){if (start == end) return;int index = Partition(arr, start, end);if (index>start) QuickSort(arr, start, index - 1);if (index < end) QuickSort(arr, index + 1, end);}/*注意:此方法也可以用来查找最小的k个数*/int GetMedium(int *arr, int size){int start = 0;int end = size - 1;int index = Partition(arr, start, end);int midIndex = (size + 1) / 2 - 1;  //下标while (index != midIndex){if (index > midIndex){end = index - 1;index = Partition(arr, start, end);}else{start = index + 1;index = Partition(arr, start, end);}}return arr[index];}int main() {int arr[] = { 2,5,9,7,1,6,4,8,3 };cout << GetMedium(arr, 9)<<endl;QuickSort(arr, 0, 8);for (int i = 0; i < 9; i++)cout << arr[i] << " ";cout << endl;return 0;}


补充:

解法四:(方法好,实现困难)
可以建立AVL树,通常AVL树的平衡因子是左右子树的高度差,可以将平衡因子修改为左右子树的结点差,这样时间复杂度为O(lgn)。且只需要遍历一次数组。

解法五:(方法好,实现容易)

用一个最大堆和最小堆也可以实现。用一个最大堆存放左边较小的数,用一个最小堆存放右边较大的数。现在关键是如何保证数据平均分配到两个堆中,使两个堆中数据数目之差不能超过1。

可以在数据的总数目是偶数时把心数据插入到最小堆,否则插入到最大堆。如果这个新插入到最小堆的数据比最大堆中的一些数据还要小,则可以先将该数据插入到最大堆,然后将最大堆中的最大数拿出插入到最小堆。

#include <iostream>    #include <vector>    #include <stack>#include <algorithm>  //堆算法#include <functional> //仿函数using namespace std;void InsertData(vector<int>&minHeap, vector<int>&maxHeap,int data){if (((minHeap.size() + maxHeap.size()) & 1) == 0)  //插入的总数目是奇数时,插入到最大堆{if (minHeap.size() > 0 && data > minHeap[0]){minHeap.push_back(data);push_heap(minHeap.begin(), minHeap.end(), greater<int>()); //插入元素后进行调整data = minHeap[0];pop_heap(minHeap.begin(), minHeap.end(), greater<int>());//把最小的元素放到最后,并调整minHeap.pop_back();                                      //去掉最后的元素,即最小的那个元素}maxHeap.push_back(data);push_heap(maxHeap.begin(), maxHeap.end(), less<int>());}else                                              //插入的总数目是偶数时,插入到最小堆{if (maxHeap.size() > 0 && data < maxHeap[0]){maxHeap.push_back(data);push_heap(maxHeap.begin(), maxHeap.end(), less<int>());data = maxHeap[0];pop_heap(maxHeap.begin(), maxHeap.end(), less<int>());maxHeap.pop_back();}minHeap.push_back(data);push_heap(minHeap.begin(), minHeap.end(), greater<int>());}}float GetMedium(){int num;         //要输入数据个数int data;        //每次存放数据vector<int> minHeap;  //最小堆vector<int> maxHeap;  //最大堆cin >> num;for (int i = 0; i < num; i++){cin >> data;InsertData(minHeap, maxHeap, data);}if (minHeap.size()>maxHeap.size()) return (float)minHeap[0];else if (minHeap.size() < maxHeap.size()) return (float)maxHeap[0];else return (minHeap[0] + maxHeap[0]) / (float)2;}int main(){float re = GetMedium();cout << re << endl;return 0;}




0 0
原创粉丝点击