63.题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路:堆插入时间复杂度O(log n)
设置最大堆 最小堆。其中最大堆的最大值<=最小堆的最小值
最大堆p–top—–top—最小堆q
插入:当p为空或者num
class Solution {
priority_queue<int,vector<int>,less<int> >p;//less最大堆
priority_queue<int,vector<int>,greater<int> >q;//最小堆
public:
bool err_flag=false;//非法操作
void Insert(int num)
{
if(p.empty()||num<p.top())//先放在最大堆中
p.push(num);
else
q.push(num);
if(p.size()>q.size()+1)//p与q的差值不能大于1
{
q.push(p.top());
p.pop();
}
if(p.size()<q.size())//p与q的差值不能小于0
{
p.push(q.top());
q.pop();
}
}
double GetMedian()
{
if(p.empty())
{
err_flag=true;
return -1;
}
return p.size()==q.size()?(p.top()+q.top())/2.0 : p.top();
}
};
class Solution {
vector<int>max;
vector<int>min;
public:
bool err_flag=false;
//奇数放在最小堆,偶数放在最大堆
void Insert(int num)
{
if((max.size()+min.size())%2==0)//odd
{
if(min.size()>0 && min[0]<num)
{
min.push_back(num);
push_heap(min.begin(),min.end(),greater<int>());
num=min[0];
pop_heap(min.begin(),min.end(),greater<int>());
min.pop_back();
}
max.push_back(num);
push_heap(max.begin(),max.end(),less<int>());
}
else
{
if(max.size()>0 && max[0]>num)
{
max.push_back(num);
push_heap(max.begin(),max.end(),less<int>());
num=max[0];
pop_heap(max.begin(),max.end(),less<int>());
max.pop_back();
}
min.push_back(num);
push_heap(min.begin(),min.end(),greater<int>());
}
}
double GetMedian()
{
if(min.size()+max.size()==0)
{
err_flag=true;
return 0;
}
return (max.size()+min.size())%2==1 ? max[0]:(max[0]+min[0])/2.0;
}
};
64.题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int>data;
if(num.size()<size || size==0)
return data;
deque<int>index;
for(int i=0;i<num.size();++i)
{
while(index.size() && num[index.back()]<num[i])//删除比当前值小的坐标
index.pop_back();
while(index.size() && i-index.front()+1>size)//删除失效坐标
index.pop_front();
index.push_back(i);
if(i+1>=size)
data.push_back(num[index.front()]);
}
return data;
}
};