剑指OFFER_数据流中的中位数
剑指OFFER_数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路
我觉得刷题的思路应该是从无到有,然后再从有到更好;
秉持着这样的思路,先从最简单的思路解这道题,按照题意先做一个容器容纳这个数据流;
然后对这个容器排序,并记录容器长度;
输出结果时,如果长度为奇数,则输出中位数,为偶数则求均值;
优化的思路就是就是sort函数,倒不是说sort函数不好用,而是其实vector中其实本来就排好顺序的,只是增加一个,所以只需要插入一个数到这个有序的容器中就好了,很自然的就想到了二分法;
好吧其实完成后也没提高多少,从5ms提升到了3ms,代码如下:
代码_暴力
class Solution {
public:
int len = 0;
vector<int> S;
void Insert(int num)
{
++len;
S.push_back(num);
// 待优化
sort(S.begin(), S.end());
}
double GetMedian()
{
if (len % 2 == 1) {
return (double)S[len/2];
}else {
return (double)(S[len/2]+S[len/2-1])/2;
}
}
};
代码_二分法
class Solution {
public:
int len = 0;
vector<int> S;
void dichotomy(int begin, int end, const int& num) {
if (end - begin <= 1) {
if (num < S[begin]) {
S.insert(S.begin()+begin, num);
}else if (num > S[end]) {
S.insert(S.begin()+end+1, num);
}else{
S.insert(S.begin()+end, num);
}
return;
}
int mid = (begin + end)/2;
if (S[mid] > num) {
dichotomy(begin, mid, num);
} else {
dichotomy(mid, end, num);
}
}
void Insert(int num)
{
if (len == 0) {
S.push_back(num);
}else {
dichotomy(0, len-1, num);
}
++len;
}
double GetMedian()
{
if (len % 2 == 1) {
return (double)S[len/2];
}else {
return (double)(S[len/2]+S[len/2-1])/2;
}
}
};