1. 程式人生 > >Leetcode 480. Sliding Window Median

Leetcode 480. Sliding Window Median

may ras numbers bsp push_back || dia tco 動態添加

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

which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Your job is to output the median array for each window in the original array.

For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k

= 3.

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