Sunday, September 29, 2019

Leetcode 480: Sliding Window Median

https://leetcode.com/problems/sliding-window-median/description/

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.

Notes:

This another design problem, which seems easy but actually it is not easy to achieve an algorithm  (or data structure, more precisely) faster than O(N*K).

This question can be viewed to one variant to another question Leetcode 239.

For this question, we can consider to use multiset, which can localize any element by the key or its value. There may be elements with the same value, thus we need multiset instead of set.

Multiset or set can order the element in O(logK) with its build-in property. When all the K elements are ordered, it is easy to figure out the median.

Of course it depends on the polarity of K. Here we adopt some very useful operators about the pointers.

See the code below:

class Solution {
public:
    vector<double> medianSlidingWindow(vector<int>& nums, int k) {
        multiset<int> mst(nums.begin(), nums.begin() + k);
        vector<double> res;
        auto mid = next(mst.begin(), k/2);//next() function
        for(int i=k; ; ++i) {
            res.push_back(((double)*mid + (double)*prev(mid, 1-k%2))/2);//prev() function
            if(i==nums.size()) return res;
            mst.insert(nums[i]);
            if(nums[i] < *mid) --mid;
            if(nums[i-k] <= *mid) ++mid;
            mst.erase(mst.lower_bound(nums[i-k]));//lower_bound() function
        }
    }
};

No comments:

Post a Comment