C++描述 LeetCode 480. 滑动窗口中位数

C++描述 LeetCode 480. 滑动窗口中位数

  大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在CSDN中写博客,唯一博客更新的地址为:亓官劼的博客 ,同时正在尝试在B站中做一些内容分享,B站主页为: 亓官劼的B站主页

本文原创为亓官劼,请大家支持原创,部分平台一直在恶意盗取博主的文章!!!
若需联系博主,可以联系本人微信:qiguanjie2015


中位数是有序序列最中间的那个数。如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。

例如:

  • [2,3,4],中位数是 3
  • [2,3],中位数是 (2 + 3) / 2 = 2.5

给你一个数组 nums,有一个大小为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

示例:

给出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。

窗口位置                      中位数
---------------               -----
[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

因此,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]

提示:

  • 你可以假设 k 始终有效,即:k 始终小于输入的非空数组的元素个数。
  • 与真实值误差在 10 ^ -5 以内的答案将被视作正确答案。

题解思路

这里一开始采用暴力解法,由于要保持原数列不变,所以每次取出当前的K个数,然后进行排序,去中位数,然后发现超时了。这里采用另一种求中位数的思路,就是我们使用划分来代替查找,因为我们只需要知道中间的数,而不需要K个数有序,以此来优化时间。这里要注意一下的是在K为偶数的时候,为了消除K为2时的边界问题,两个数采用s[k/2]和s[(k-1)/2]更方便,不需要特殊处理边界。这里划分采用nth_element()函数,此函数在STL库中。在此优化之后,卡线过关。有兴趣的也可以采用双优先队列+延迟删除来做,来进一步优化时间

算法实现

class Solution {
public:
    vector<double> medianSlidingWindow(vector<int>& nums, int k) {
        vector<double> ans;
        vector<int> s(k);
        int r = nums.size() - k;
        for(int i = 0 ; i <= r; i++){
            for(int j = 0 ; j < k; j++){
                s[j] = nums[i+j];
            }
            // sort(s.begin(),s.begin()+k);
            if(k%2 == 1){
                //k为奇数时,中间一项
                // nth_element为划分函数,常用于找第k大的数
                nth_element(s.begin(),s.begin()+k/2,s.begin()+k);
                ans.push_back(s[k/2]);
            }else{
                // K为偶数时,中间两项,这里两项相加要先换成double,不然容易溢出
                nth_element(s.begin(),s.begin()+k/2,s.begin()+k);
                double mid = s[k/2];
                nth_element(s.begin(),s.begin()+(k-1)/2,s.begin()+k);
                ans.push_back((mid+s[(k-1)/2])/2.0);
            }
        }
        return ans;
    }
};
  • 25
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 31
    评论
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亓官劼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值