classSolution { public: voidpush(deque<long> &window, int value){ int back = window.back(); stack<long> preserve; while (back > value && !window.empty()) { preserve.push(back); window.pop_back(); back = window.back(); }
window.push_back(value); while (!preserve.empty()) { long top = preserve.top(); window.push_back(top); preserve.pop(); } }
vector<double> medianSlidingWindow(vector<int>& nums, int k) { vector<double> medians;
if (nums.empty()) return medians;
for (int i = 0; i < nums.size() - (k - 1); ++i) { deque<long> window {nums[i]};
for (int j = i + 1; j <= i + (k - 1); ++j) { int front = window.front(), back = window.back(); if (nums[j] <= front) { window.push_front(nums[j]); } else { if (nums[j] >= back) { window.push_back(nums[j]); } else { push(window, nums[j]); } } }
double median = 0; if (k % 2 == 0) { median = (window[k / 2] + window[k / 2 - 1]) / (double)2; } else { median = window[k / 2]; } medians.push_back(median); }
return medians; } };
对于简单的用例,上述方法能够正确获得中位数序列,但假如输入的用例比较复杂呢?超时的问题如何解决?
方法二
首先,我们维护两个堆:
一个大根堆 lo,用来存放较小的那一半的元素;
一个小根堆 hi,用来存放较大的那一半的元素。
由此,堆顶的元素即为中位数。接下来,使用哈希集合(HashSet)或者哈希映射(HashMap),记为 hash_table,标记所有被移除的无效元素,哈希表的大小等于在堆中无效元素的数量;大根堆 lo 最多允许比小根堆 hi 存放多一个元素,当我们已经处理了 k 个元素时:
如果 k = 2n + 1 为奇数,那么 lo 中存储 k + 1 个元素,hi 中存储 k 个元素;
如果 k = 2n 为偶数,那么 lo 和 hi 中都存储 k 个元素;
如何判断两个堆是否平衡呢?我们引入balance变量,表示两个堆是否平衡:
如果 balance == 0,那么两个堆平衡;
如果 balance < 0,那么 lo 中的元素较少,需要从 hi 中取出若干个元素放入 lo;
如果 balance > 0,那么 hi 中的元素较少,需要从 lo 中取出若干个元素放入 hi。
此时我们需要插入一个新的元素 in_num:
如果 in_num 小于等于 lo 的堆顶元素,那么它可以被放入 lo 中,此时需要增加 balance 的值;
// number `in_num` enters window if (!lo.empty() && in_num <= lo.top()) { balance++; lo.push(in_num); } else { balance--; hi.push(in_num); }
// re-balance heaps if (balance < 0) { // `lo` needs more valid elements lo.push(hi.top()); hi.pop(); balance++; } if (balance > 0) { // `hi` needs more valid elements hi.push(lo.top()); lo.pop(); balance--; }
// remove invalid numbers that should be discarded from heap tops while (hash_table[lo.top()]) { hash_table[lo.top()]--; lo.pop(); } while (!hi.empty() && hash_table[hi.top()]) { hash_table[hi.top()]--; hi.pop(); } }