滑动窗口的中位数-LintCode

本文介绍了一种求解滑动窗口内中位数的高效算法,通过使用两个有序集合来维护窗口内的数据,实现了O(nlog(n))的时间复杂度。文章详细解释了算法流程,并提供了完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中滑动这个窗口,找到数组中每个窗口内的中位数。(如果数组个数是偶数,则在该窗口排序数字后,返回第 N/2 个数字。)

样例:
对于数组 [1,2,7,8,5], 滑动大小 k = 3 的窗口时,返回 [2,7,7]

最初,窗口的数组是这样的:
[ | 1,2,7 | ,8,5] , 返回中位数 2;
接着,窗口继续向前滑动一次。
[1, | 2,7,8 | ,5], 返回中位数 7;
接着,窗口继续向前滑动一次。
[1,2, | 7,8,5 | ], 返回中位数 7;

挑战:
时间复杂度为 O(nlog(n))

#ifndef C360_H
#define C360_H
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
class Solution {
public:
    /*
    * @param nums: A list of integers
    * @param k: An integer
    * @return: The median of the element inside the window at each moving
    */
    vector<int> medianSlidingWindow(vector<int> &nums, int k) {
        // write your code here
        vector<int> v;
        if (nums.empty() || k == 0)
            return v;
        if (k == 1)
            return nums;
        int len = nums.size();
        if (k >= len)
        {
            sort(nums.begin(), nums.end());
            v.push_back(nums.size() % 2 == 0 ? nums[nums.size() / 2 - 1] : nums[nums.size() / 2]);
            return v;
        }
        multiset<int> rset, lset;
        for (int i = 0; i < len; ++i)
        {
            if (i >= k)
            {
                if (lset.count(nums[i - k]))
                    lset.erase(lset.find(nums[i - k]));
                else 
                    rset.erase(rset.find(nums[i - k]));
            }
            if (lset.size() <= rset.size())
            {
                if (rset.empty() || nums[i] <= *rset.begin())
                    lset.insert(nums[i]);
                else
                {
                    lset.insert(*rset.begin());
                    rset.erase(rset.begin());
                    rset.insert(nums[i]);
                }
            }
            else
            {
                if (nums[i] >= *lset.rbegin())
                    rset.insert(nums[i]);
                else
                {
                    rset.insert(*lset.rbegin());
                    lset.erase(--lset.end());
                    lset.insert(nums[i]);
                }
            }
            if (i + 1 >= k)
            {
                v.push_back(*lset.rbegin());
            }
        }
        return v;
    }
};
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值