共计 2184 个字符,预计需要花费 6 分钟才能阅读完成。
480. 滑动窗口中位数
难度 艰难
中位数是有序序列最两头的那个数。如果序列的长度是偶数,则没有最两头的数;此时中位数是最两头的两个数的平均数。
例如:
[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 1
1 [3 -1 -3] 5 3 6 7 -1
1 3 [-1 -3 5] 3 6 7 -1
1 3 -1 [-3 5 3] 6 7 3
1 3 -1 -3 [5 3 6] 7 5
1 3 -1 -3 5 [3 6 7] 6
因而,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]。
// 暴力解法
class Solution1 {
public:
vector<double> medianSlidingWindow(vector<int> &nums, int k) {int size = nums.size();
vector<double> res;
for (int i = 0; i < size - k + 1; ++i) {vector<int> temp(nums.begin() + i, nums.begin() + i + k);
sort(temp.begin(), temp.end());
if (k & 1) {res.emplace_back(temp[k / 2]);
} else {res.emplace_back((temp[k / 2] + temp[k / 2 - 1]) / 2.0);
}
}
return res;
}
};
// 官网解法,规范性好
class DualHeap {
private:
priority_queue<int, vector<int>, less<int>> small; // 大根堆存比拟小的数
priority_queue<int, vector<int>, greater<int>> large; // 小根堆存比拟大的数
unordered_map<int, int> delay;
int smallSize;
int largeSize;
int k;
public:
DualHeap(int _k) : k(_k), smallSize(0), largeSize(0) {}
template<class T>
void pop(T &heap) {while (!heap.empty()) {int temp = heap.top();
if (delay.count(temp)) {--delay[temp];
if (delay[temp] == 0)
delay.erase(temp);
heap.pop();} else
break;
}
}
void balance() {if (smallSize-2 == largeSize) {large.emplace(small.top());
small.pop();
--smallSize;
++largeSize;
pop(small);
}
if (smallSize < largeSize) {small.emplace(large.top());
large.pop();
--largeSize;
++smallSize;
pop(large);
}
}
void insert(int x) {if (small.empty() || x <= small.top()) {small.emplace(x);
++smallSize;
} else {large.emplace(x);
++largeSize;
}
balance();}
void erase(int x) {++delay[x];
if (x <= small.top()) {
--smallSize;
if (x == small.top())
pop(small);
} else {
--largeSize;
if (x == large.top()) {pop(large);
}
}
balance();}
double getMedian() {return k & 1 ? small.top() : small.top() / 2.0 + large.top() / 2.0;
}
};
class Solution2 {
public:
vector<double> medianSlidingWindow(vector<int> &nums, int k) {int size = nums.size();
DualHeap dh(k);
vector<double> res;
for (int j = 0; j < k; ++j) {dh.insert(nums[j]);
}
for (int i = k, j = 0; i <= size; ++i, ++j) {res.emplace_back(dh.getMedian());
dh.insert(nums[i]);
dh.erase(nums[j]);
}
res.emplace_back(dh.getMedian()); // 要害
return res;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/sliding-window-median/solution/hua-dong-chuang-kou-zhong-wei-shu-by-lee-7ai6/
起源:力扣(LeetCode)
正文完