第一次写题
这道题最大的难点在于想清楚插入到哪一个堆,又从哪一个堆删除数据。我们一开始用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 0balance += (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;}};
