hard-480. Sliding Window Median

问题

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.

## 代码
```C++
class Solution {
public:
    //方法一:通过率30/42,当窗口长度=3000+时,运行超时
    vector<double> medianSlidingWindow(vector<int>& nums, int k) {
        //if(k == 1) return nums;
        vector<double> result;
        for(int i=0; i<=nums.size()-k; i++)
        {
            result.push_back(getMedian(nums,i,k));
        }
        return result;
    }

    double getMedian(vector<int>& nums, int left, int k)
    {
        //使用 make_heap(): 并没有排序功能。。。不如直接sort来得干脆
        vector<int> temp(nums.begin()+left,nums.begin()+left+k);
        //make_heap(temp.begin(), temp.end());
        sort(temp.begin(), temp.end());
        if(k%2 == 1)
            return temp[k/2];
        else if(k%2 == 0)
            //return ((double)(temp[k/2]+temp[k/2-1]))/2.0;   //若先加,可能会两个正数之和超出int表示范围从而变成负数。
            return (double)temp[k/2]/2.0 + (double)temp[k/2-1]/2.0;
    }


    //方法二:multiset
    vector<double> medianSlidingWindow(vector<int>& nums, int k) {
    multiset<int> window(nums.begin(), nums.begin() + k);
    auto mid = next(window.begin(), k / 2);
    vector<double> medians;
    for (int i=k; ; i++) {

        // Push the current median.
        medians.push_back((double(*mid) + *prev(mid, 1 - k%2)) / 2);

        // If all done, return.
        if (i == nums.size())
            return medians;

        // Insert nums[i].
        window.insert(nums[i]);
        if (nums[i] < *mid)
            mid--;

        // Erase nums[i-k].
        if (nums[i-k] <= *mid)
            mid++;
        window.erase(window.lower_bound(nums[i-k]));
       }
    }

};

总结

  • 上面代码使用到了 next()、 prev()等函数,用来将迭代器左移或者右移若干位。
  • 在set中,数据都是有序的,默认从小到大。在有序的数列中,想要删除某个数,使用window.erase(window.lower_bound(nums[i-k])),
    也就是 erase()+ lower_bound(target)的组合操作,可以删除target。
  • 在顺序容器中,使用sort()、lower_bound()、upper_bound()、find()等STL算法,一般都不是成员函数方式访问,
    而是 sort(xx.begin(), xx.end(), xxx) 之类;
    而在关联容器中,一般则是成员函数方式访问,比如 iset.find(target) 这种。可以参考一下STL源码分析。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值