题目描述:数据流的中位数。
题目要求实现一个插入操作,和返回中位数的操作。
这里插入后要时时排序, 并索引中位数, 整个算法可以从一下角度思考:
插入灵活(数组|链表|等)+排序复杂度低+索引迅速。
首先先用暴力法走一遍流程(数组(插入开销大 但 索引迅速)+冒泡(简单))
class Solution {
public:
vector<int> arr;
void Insert(int num) {
arr.push_back(num);
}
double GetMedian() {
//----自带sort算法
sort(arr.begin(), arr.end());
int len = arr.size();
if (len & 1 ){
return double(arr[len >> 1]);
}else{
return double(arr[len >> 1] + arr[(len-1) >> 1]) /2 ;
}
}
};使用自己的冒泡排序
class Solution {
public:
vector<int> arr;
void Insert(int num) {
arr.push_back(num);
}
double GetMedian() {
//----自带sort算法
//sort(arr.begin(), arr.end());
//----自己写sort:冒泡
int len = arr.size();
int tmp = 0;
for(int i=0; i<len; i++)
for(int j =0; j<len-i-1; j++)
if(arr[j] > arr[j+1]){
tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp;
}
if (len & 1 ){
return double(arr[len >> 1]);
}else{
return double(arr[len >> 1] + arr[(len-1) >> 1]) /2 ;
}
}
};至此, 已经可以发现, 想要优化, 就应当思考不同排序算法的效率,以及数据形式,是否易于插入, 索引。
我自己想到一个改进是利用插入排序, 因为插入排序可以在插入时就维护好数组升序, 从而返回中位数时只要索引即可。这样的排序的复杂度每次是O(N)。
class Solution {
public:
vector<int> arr;
void Insert(int num) {
if(arr.empty())
arr.push_back(num);
else{
//自带的插入
auto it = lower_bound(arr.begin(),arr.end(),num);
arr.insert(it, num);
}
}
double GetMedian() {
int len = arr.size();
if (len & 1 ){
return double(arr[len >> 1]);
}else{
return double(arr[len >> 1] + arr[(len-1) >> 1]) /2 ;
}
}
};自己的插入写法:
class Solution {
public:
vector<int> arr;
void Insert(int num) {
arr.push_back(num);
int i=0;
for(i = arr.size()-1; i>0; i--)
if(num < arr[i-1])
arr[i] = arr[i-1];
else
break;
arr[i] = num;
}
double GetMedian() {
int len = arr.size();
if (len & 1 ){
return double(arr[len >> 1]);
}else{
return double(arr[len >> 1] + arr[(len-1) >> 1]) /2 ;
}
}
};如果考虑到数据结构和排序算法的结合:
1、数组:插入困难, 索引容易
2、链表: 插入简单, 索引困难;
3、树:存储有序, 方便索引,排序调整。
这里具体我也不太熟悉, 刚开始学习, 后期会优化, 这里给出大小顶堆的方法:
如果对于中位数左侧利用大顶堆, 则左侧升序, 对右侧利用小顶堆, 则右侧有序, 这样方便插入,排序, 以及返回中位数。
class Solution {
public:
priority_queue<int> min_q;
priority_queue<int, vector<int>, greater<int>> max_q;
void Insert(int num) {
//若一开始两个堆长度相同,平衡后仍然相同
min_q.push(num);
max_q.push(min_q.top());
min_q.pop();
//左小于右, 左右差1, 将mid维护到左(大)堆中去
if(min_q.size()< max_q.si***_q.push(max_q.top());
max_q.pop();
}
}
double GetMedian() {
//return min_q.size() > max_q.size()? double(min_q.top()):double(min_q.top()+max_q.top())/2;
if(min_q.size()>max_q.size())
return double(min_q.top());
else
return double(min_q.top() + max_q.top())/2;
}
};果然STL库用起来很爽, 看来要好好学习下。

京公网安备 11010502036488号