题目:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路:
1.用vector保存,get时先排序后取。
插入复杂度O(1) ,get复杂度O(nlogn)
2.分别用大顶堆和小顶堆保存左右两部分,左边一定比右边小,且左右两部分size之差不超过一,get时根据两边size情况去堆顶数据即可。
插入复杂度O(logn),get复杂度O(1)
代码:
//方法1
class Solution {
public:
void Insert(int num)
{
m_data.push_back(num);
}
double GetMedian()
{
sort(m_data.begin(), m_data.end())
int size = m_data.size();
if (size == 0)
return (double)0;
if(size%2 == 0)
return ((double)m_data[size/2] + (double)m_data[size/2 - 1])/2;
else
return (double)m_data[size/2];
}
vector<int> m_data;
};
//方法2
class Solution {
public:
void Insert(int num)
{
int left_size = m_queue_left.size();
int right_size = m_queue_right.size();
//这里是初始时有可能为空
int left_top = m_queue_left.empty() ? INT_MAX : m_queue_left.top();
int right_top = m_queue_right.empty() ? INT_MIN : m_queue_right.top();
//需要插入左边
if (left_top > num)
{
if(left_size <= right_size)
{
m_queue_left.push(num);
}
else
{
m_queue_left.pop();
m_queue_left.push(num);
m_queue_right.push(left_top);
}
}
//需要插入右边
else
{
if(left_size >= right_size)
{
m_queue_right.push(num);
}
else
{
m_queue_right.pop();
m_queue_right.push(num);
m_queue_left.push(right_top);
}
}
}
double GetMedian()
{
int left_size = m_queue_left.size();
int right_size = m_queue_right.size();
if(0 == left_size && 0 == right_size)
{
return 0;
}
else if(0 == left_size)
{
return (double)m_queue_right.top();
}
else if(0 == right_size)
{
return (double)m_queue_left.top();
}
int right_top = m_queue_right.top();
int left_top = m_queue_left.top();
if(left_size == right_size)
{
return ((double)left_top + (double)right_top)/2;
}
return (left_size > right_size) ? (double)left_top : (double)right_top;
}
//右侧数字都比左侧数字大,且两个堆个数相差不能超过1
priority_queue<int,vector<int>,greater<int> > m_queue_right;//小顶堆 存放右侧数字
priority_queue<int,vector<int>,less<int> > m_queue_left;//大顶堆 存放右左侧数字
};