1. 题目
中位数是有序序列最中间的那个数。
如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
例如:
[2,3,4],中位数是 3
[2,3],中位数是 (2 + 3) / 2 = 2.5
给你一个数组 nums,有一个大小为 k 的窗口从最左端滑动到最右端。
窗口中有 k 个数,每次窗口向右移动 1 位。
你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。
示例:
给出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。窗口位置 中位数
--------------- -----
[1 3 -1] -3 5 3 6 7 11 [3 -1 -3] 5 3 6 7 -11 3 [-1 -3 5] 3 6 7 -11 3 -1 [-3 5 3] 6 7 31 3 -1 -3 [5 3 6] 7 51 3 -1 -3 5 [3 6 7] 6因此,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]。提示:
你可以假设 k 始终有效,即:k 始终小于输入的非空数组的元素个数。
与真实值误差在 10 ^ -5 以内的答案将被视作正确答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sliding-window-median
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
类似题目:
LeetCode 295. 数据流的中位数(大小堆)
LeetCode 703. 数据流中的第K大元素(优先队列)
参考我的博客 数据结构 堆(优先队列)
参考大小堆的思想,一个堆最多比另一个堆最多多一个元素,不再多讲,请参考上面链接
- 关键要实现从堆中删除窗口左端点,那么用 set 来当做堆就可以突破优先队列(堆)不能删除非堆顶元素
- 本题:
小堆size = 大堆size
or小堆size = 大堆size+1
- k 为 奇数,直接返回小堆顶 set.begin()
- k 为 偶数,返回两个堆顶的平均值
class Solution { // C++multiset<int> minheap;//begin 是小的元素multiset<int,greater<int>> maxheap;//begin 是大的元素
public:vector<double> medianSlidingWindow(vector<int>& nums, int k) {// k = 1,直接返回数组if(k == 1) return vector<double>(nums.begin(), nums.end());int n = nums.size(), i = 0, j = 0, idx = 0;long a, b;//避免溢出 longvector<double> ans(n-k+1);for( ; j < k; ++j)maxheap_minheap_add(nums[j]);//先加入k个a = (*maxheap.begin()), b = (*minheap.begin());ans[idx++] = (k&1) ? b : (a+b)/2.0;//记录中位数for(i = 0 ; j < n; ++i,++j){maxheap_minheap_del(nums[i]);//删除左端点maxheap_minheap_add(nums[j]);//加入右端点a = (*maxheap.begin()), b = (*minheap.begin());ans[idx++] = (k&1) ? b : (a+b)/2.0;//记录中位数}return ans;}void maxheap_minheap_add(int x){if(minheap.empty())minheap.insert(x);else if(maxheap.size() == minheap.size()){if(x >= *maxheap.begin())minheap.insert(x);else{minheap.insert(*maxheap.begin());maxheap.erase(maxheap.begin());maxheap.insert(x);}}else if(maxheap.size() < minheap.size()){if(x <= *minheap.begin())maxheap.insert(x);else{maxheap.insert(*minheap.begin());minheap.erase(minheap.begin());minheap.insert(x);}}}void maxheap_minheap_del(int x){if(maxheap.size() < minheap.size()){auto it = minheap.find(x);if(it != minheap.end())minheap.erase(it);else{maxheap.erase(maxheap.find(x));maxheap.insert(*minheap.begin());minheap.erase(minheap.begin());}}else if(maxheap.size() == minheap.size()){auto it = maxheap.find(x);if(it != maxheap.end())maxheap.erase(it);else{minheap.erase(minheap.find(x));minheap.insert(*maxheap.begin());maxheap.erase(maxheap.begin());}}}
};
108 ms 18.9 MB