Leetcode 480. Sliding Window Median
Problem:
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples:[2,3,4]
, the median is 3
[2,3]
, the median is (2 + 3) / 2 = 2.5
Given an array nums, there is a sliding window of size k
For example,
Given nums = [1,3,-1,-3,5,3,6,7]
, and k
Window position Median --------------- ----- [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
Therefore, return the median sliding window as [1,-1,-1,3,5,6]
Note:
You may assume k
is always valid, ie: k
is always smaller than input array‘s size for non-empty array.
Solution:
這道題思路不難,但寫起來有點麻煩,看到這道題,發現和Leetcode 239. Sliding Window Maximum非常相似,但最大值和中值的處理卻幾乎完全不同,然後考慮用雙優先級隊列, 但優先級隊列的刪除操作卻非常影響效率,既要刪除比較快,又要速度快,map是最好的選擇了,一般來說,能用優先級隊列的題目用map也能解決。考慮到可能存在重復的數字,所以用left和right兩個變量記錄small和big兩個map的數字和(不能簡單的用map.size()),動態添加和刪除即可。
Code:
1 class Solution { 2 public: 3 void addValue(map<int,int> &small,map<int,int> &big,int &left,int &right,int &value){ 4 if(left == right){ 5 if(small.empty() || value <= small.rbegin()->first){ 6 small[value]++; 7 } 8 else{ 9 big[value]++; 10 small[big.begin()->first]++; 11 big[big.begin()->first]--; 12 if(big[big.begin()->first] == 0) 13 big.erase(big.begin()->first); 14 } 15 left++; 16 } 17 else{ 18 if(value <= small.rbegin()->first){ 19 small[value]++; 20 big[small.rbegin()->first]++; 21 small[small.rbegin()->first]--; 22 if(small[small.rbegin()->first] == 0) 23 small.erase(small.rbegin()->first); 24 } 25 else{ 26 big[value]++; 27 } 28 right++; 29 } 30 } 31 vector<double> medianSlidingWindow(vector<int>& nums, int k) { 32 vector<double> result; 33 bool flag = k%2; 34 int left = 0,right = 0; 35 map<int,int> small,big; 36 for(int i = 0;i != k;++i){ 37 addValue(small,big,left,right,nums[i]); 38 } 39 result.push_back(flag?(small.rbegin()->first):((int64_t)(small.rbegin()->first)+(int64_t)(big.begin()->first))/2.0); 40 for(int i = k;i != nums.size();++i){ 41 int prev = nums[i-k]; 42 if(prev <= small.rbegin()->first){ 43 small[prev]--; 44 if(small[prev] == 0) 45 small.erase(prev); 46 if(!flag){ 47 small[big.begin()->first]++; 48 big[big.begin()->first]--; 49 if(big[big.begin()->first] == 0) 50 big.erase(big.begin()->first); 51 right--; 52 } 53 else 54 left--; 55 } 56 else{ 57 big[prev]--; 58 if(big[prev] == 0) 59 big.erase(prev); 60 if(flag){ 61 big[small.rbegin()->first]++; 62 small[small.rbegin()->first]--; 63 if(small[small.rbegin()->first] == 0) 64 small.erase(small.rbegin()->first); 65 left--; 66 } 67 else 68 right--; 69 } 70 addValue(small,big,left,right,nums[i]); 71 result.push_back(flag?(small.rbegin()->first):((int64_t)(small.rbegin()->first)+(int64_t)(big.begin()->first))/2.0); 72 } 73 return result; 74 } 75 };
Leetcode 480. Sliding Window Median