第一次写题
这道题最大的难点在于想清楚插入到哪一个堆,又从哪一个堆删除数据。我们一开始用balance = 0表示数量平衡的状态,最大堆比最小堆多,balance就+1,比最小堆少balance就-1。插入最大堆相当于最大堆增多是balance +1,删除最大堆的元素相当于是balance -1。插入到最小堆是balance - 1,删除最大堆的元素是balance +1。
从最大堆(max_heap)删除数据会让balance -1,插入最小堆(min_heap)会让balance -1,因为前一轮max_heap的top和min_heap的top都是可以用的,现在从max_heap删除,插入到min_heap,能确定的是min_heap的top是可以用的!并且max_heap现在是少了东西,需要从min_heap拿。因此直接拿min_heap的top就可以。
还有一个问题是,为什么balance = -2只要转移一个数据?不是转移两个数据?首先,要想清楚的是,如果a是奇数,然后分成两堆a1、 a2,必然是a1、a2中一个奇数一个偶数。因此我们从一堆中删除一个并不影响它的平衡(虽然说我们是希望让最大堆的比最小堆的多一个数字,但是最小堆比最大堆多一个数字也不是不平衡)。因此删掉了一个还是平衡的,那么再插入一个呢?这个时候如果插入的是对面的堆,那么balance = -2。一边少了一个,另外一边多了一个,本来少了的就少了也是平衡。但是现在对面的多了一个就应该把这个多的给来这边,继续保持数量上的平衡。
class Solution {
public:
vector<double> medianSlidingWindow(vector<int>& nums, int k) {
priority_queue<int> max_heap;
priority_queue<int, vector<int>, greater<int>> min_heap;
for(int i = 0; i < k; i++)
max_heap.push(nums[i]);
for(int i = 0; i < k/2; i++)
{
min_heap.push(max_heap.top());
max_heap.pop();
}
vector<double> res;
map<int, int> mp;
for(int i = k; i <= nums.size(); i++)
{
// cout << min_heap.top() << ' ' << max_heap.top() << endl;
res.push_back(k & 1? max_heap.top(): 0.5 * min_heap.top() + 0.5 * max_heap.top());
if(i == nums.size()) break;
int balance = 0;//这里容易错,删去max_heap,插入min_heap 这样balance = -2!
//其实是有几种情况的,1.删除和插入是max_heap 0 2.删除min插入max -2 3.删除max插入min 2 4.删除和插入都是min 0
balance += (nums[i - k] <= max_heap.top()? -1: 1);
mp[nums[i - k]]++;
if(nums[i] <= max_heap.top())
{
max_heap.push(nums[i]);
balance++;
}
else
{
min_heap.push(nums[i]);
balance--;
}
if(balance > 0)
{
min_heap.push(max_heap.top());
max_heap.pop();
}
if(balance < 0)
{
max_heap.push(min_heap.top());
min_heap.pop();
}
while(max_heap.size() && mp[max_heap.top()] >= 1)
{
mp[max_heap.top()]--;
max_heap.pop();
}
while(min_heap.size() && mp[min_heap.top()] >= 1)
{
mp[min_heap.top()]--;
min_heap.pop();
}
}
return res;
}
};
第二次写题
class Solution {
public:
vector<double> medianSlidingWindow(vector<int>& nums, int k) {
vector<double> aRes;
priority_queue<int> aMaxHeap;
priority_queue<int, vector<int>, greater<int>> aMinHeap;
map<int, int> aDel;
for(int i = 0; i < k; i++)
{
aMaxHeap.push(nums[i]);
}
for(int i = 0; i < k/2; i++)
{
aMinHeap.push(aMaxHeap.top());
aMaxHeap.pop();
}
for(int i = k; i <= nums.size(); i++)
{
// cout << aMinHeap.top() << endl;
// cout << aMaxHeap.top() << endl;
// cout <<(double)aMinHeap.top() * 0.5 + (double)aMaxHeap.top() * 0.5 << endl;
aRes.push_back(k & 1? aMaxHeap.top():(double)aMinHeap.top() * 0.5 + (double)aMaxHeap.top() * 0.5);
if(i == nums.size()) break;
int balance = nums[i - k] <= aMaxHeap.top()? -1:1;
aDel[nums[i - k]]++;
if(nums[i] <= aMaxHeap.top())
{
aMaxHeap.push(nums[i]);
balance++;
}
else
{
aMinHeap.push(nums[i]);
balance--;
}
if(balance < 0)
{
aMaxHeap.push(aMinHeap.top());
aMinHeap.pop();
}
else if(balance > 0)
{
aMinHeap.push(aMaxHeap.top());
aMaxHeap.pop();
}
while(aMaxHeap.size() && aDel[aMaxHeap.top()] > 0)
{
aDel[aMaxHeap.top()]--;
aMaxHeap.pop();
}
while(aMinHeap.size() && aDel[aMinHeap.top()] > 0)
{
aDel[aMinHeap.top()]--;
aMinHeap.pop();
}
}
return aRes;
}
};