Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >LeetCode 480. 滑动窗口中位数(大小堆升级版+set实现)

LeetCode 480. 滑动窗口中位数(大小堆升级版+set实现)

作者头像
Michael阿明
发布于 2020-07-13 07:52:29
发布于 2020-07-13 07:52:29
55100
代码可运行
举报
运行总次数:0
代码可运行

1. 题目

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

例如: [2,3,4],中位数是 3 [2,3],中位数是 (2 + 3) / 2 = 2.5 给你一个数组 nums,有一个大小为 k 的窗口从最左端滑动到最右端。 窗口中有 k 个数,每次窗口向右移动 1 位。 你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
示例:
给出 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 以内的答案将被视作正确答案。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/sliding-window-median 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

参考大小堆的思想,一个堆最多比另一个堆最多多一个元素,不再多讲

  • 关键要实现从堆中删除窗口左端点,那么用 set 来当做堆就可以突破优先队列(堆)不能删除非堆顶元素
  • 本题:小堆size = 大堆size or 小堆size = 大堆size+1
  • k 为 奇数,直接返回小堆顶 set.begin()
  • k 为 偶数,返回两个堆顶的平均值
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {	// C++
    multiset<int> minheap;//begin 是小的元素
    multiset<int,greater<int>> maxheap;//begin 是大的元素
public:
    vector<double> medianSlidingWindow(vector<int>& nums, int k) {
    	// k = 1,直接返回数组
        if(k == 1) return vector<double>(nums.begin(), nums.end());
        int n = nums.size(), i = 0, j = 0, idx = 0;
        long a, b;//避免溢出 long
        vector<double> ans(n-k+1);
        for( ; j < k; ++j)
            maxheap_minheap_add(nums[j]);//先加入k个
        a = (*maxheap.begin()), b = (*minheap.begin());
        ans[idx++] = (k&1) ? b : (a+b)/2.0;//记录中位数
        for(i = 0 ; j < n; ++i,++j)
        {
            maxheap_minheap_del(nums[i]);//删除左端点
            maxheap_minheap_add(nums[j]);//加入右端点
            a = (*maxheap.begin()), b = (*minheap.begin());
            ans[idx++] = (k&1) ? b : (a+b)/2.0;//记录中位数
        }
        return ans;
    }

    void maxheap_minheap_add(int x)
    {
        if(minheap.empty())
            minheap.insert(x);
        else if(maxheap.size() == minheap.size())
        {
            if(x >= *maxheap.begin())
                minheap.insert(x);
            else
            {
                minheap.insert(*maxheap.begin());
                maxheap.erase(maxheap.begin());
                maxheap.insert(x);
            }
        }
        else if(maxheap.size() < minheap.size())
        {
            if(x <= *maxheap.begin())
                maxheap.insert(x);
            else
            {
                maxheap.insert(*minheap.begin());
                minheap.erase(minheap.begin());
                minheap.insert(x);
            }
        }
    }
    void maxheap_minheap_del(int x)
    {
        if(maxheap.size() < minheap.size())
        {
            auto it = minheap.find(x);
            if(it != minheap.end())
                minheap.erase(it);
            else
            {
                maxheap.erase(maxheap.find(x));
                maxheap.insert(*minheap.begin());
                minheap.erase(minheap.begin());
            }
        }
        else if(maxheap.size() == minheap.size())
        {
            auto it = maxheap.find(x);
            if(it != maxheap.end())
                maxheap.erase(it);
            else
            {
                minheap.erase(minheap.find(x));
                minheap.insert(*maxheap.begin());
                maxheap.erase(maxheap.begin());
            }
        }
    }
};

108 ms 18.9 MB

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/06/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
每日算法题:Day 31(Linux)
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。
算法工程师之路
2019/09/10
4880
一道简约而不简单的算法题--数据流的中位数
题目来源于 LeetCode 上第 295 号问题:数据流的中位数。难度级别为 Hard,目前通过率为 33.5% 。
五分钟学算法
2019/05/06
6640
一道简约而不简单的算法题--数据流的中位数
POJ 1442 Black Box(大小堆,求第K小的元素)
可以利用大小堆,大堆长度从1开始,每次+1 大堆元素都比小堆的小,那么大堆顶的元素就是第k小的元素
Michael阿明
2021/02/20
3260
POJ 1442 Black Box(大小堆,求第K小的元素)
​LeetCode刷题实战480:滑动窗口中位数
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/12/27
4530
​LeetCode刷题实战480:滑动窗口中位数
【LeetCode 热题 100】滑动窗口最大值 / 最小覆盖子串 / 轮转数组 / 缺失的第一个正数
_小羊_
2025/04/26
660
【LeetCode 热题 100】滑动窗口最大值 / 最小覆盖子串 / 轮转数组 / 缺失的第一个正数
【数据结构与算法】堆
,总的交换次数为 $$ \begin{aligned} & 4 * 0 + 2 * 1 + 1 * 2 \
程序员波特
2024/09/27
820
【数据结构与算法】堆
LeetCode 295. 数据流的中位数(大小堆)
类似题目: LeetCode 480. 滑动窗口中位数(大小堆升级版+set实现) LeetCode 703. 数据流中的第K大元素(优先队列)
Michael阿明
2020/07/13
5930
LeetCode 295. 数据流的中位数(大小堆)
数据结构--堆 Heap
堆排序代码见:https://blog.csdn.net/qq_21201267/article/details/80993672#t7
Michael阿明
2021/02/20
2990
数据结构--堆 Heap
【刷穿 LeetCode】480. 滑动窗口中位数(困难)
一个直观的做法是:对每个滑动窗口的数进行排序,获取排序好的数组中的第 k / 2 和 (k - 1) / 2 个数(避免奇偶数讨论),计算中位数。
宫水三叶的刷题日记
2021/02/20
4290
POJ1003/1004/1005/1207/3299/2159/1083/3094/2388解题(刷一波水题)
POJ 1003 题目链接 http://poj.org/problem?id=1003 大意:长度=1/2+1/3+…+1/n,给定长度值,求n #include<iostream> usi
Michael阿明
2021/02/20
2110
POJ1003/1004/1005/1207/3299/2159/1083/3094/2388解题(刷一波水题)
10 道 BAT 大厂海量数据面试题(附题解+方法总结)
•如何从大量的 URL 中找出相同的 URL?(百度)•如何从大量数据中找出高频词?(百度)•如何找出某一天访问百度网站最多的 IP?(百度)•如何在大量的数据中找出不重复的整数?(百度)•如何在大量的数据中判断一个数是否存在?(腾讯)•如何查询最热门的查询串?(腾讯)•如何统计不同电话号码的个数?(百度)•如何从 5 亿个数中找出中位数?(百度)•如何按照 query 的频度排序?(百度)•如何找出排名前 500 的数?(腾讯)
五分钟学算法
2019/12/06
3.1K0
LeetCode *480. 滑动窗口中位数(滑动窗口)
中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
SakuraTears
2022/01/13
4060
leetcode 1438. 绝对差不超过限制的最长连续子数组----双指针篇3,滑动窗口篇2
如果是erase(3),会删除所有值为3的元素,因此我们再解题时,要给他一个迭代器,要他删除找到的第一个重复元素:
大忽悠爱学习
2021/11/15
3710
【python-leetcode480-双堆】滑动窗口的中位数
中位数是有序序列最中间的那个数。如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
西西嘛呦
2020/08/26
8060
LeetCode 295.数据流的中位数 - JavaScript
题目描述:中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
心谭博客
2020/04/21
7180
LeetCode 第 187 场周赛(1336/3107,前43.0%)
全国排名:1336 / 3107,43.0%;全球排名:5345 / 12349,43.3%
Michael阿明
2020/07/13
4130
LeetCode 第 187 场周赛(1336/3107,前43.0%)
文心一言 VS 讯飞星火 VS chatgpt (241)-- 算法导论17.3 7题
七、为动态整数多重集 S (允许包含重复值)设计一种数据结构,支持如下两个操作:① INSERT(S,x) 将 x 插入 S 中;② DELETE-LARGER-HALF(S) 将最大的 ⌈|S|/2⌉ 个元素从S中删除。解释如何实现这种数据结构,使得任意 m 个 INSERT 和 DELETE-LARGER-HAIF 操作的序列能在 O(m) 时间内完成。还要实现一个能在 O(|S|) 时间内输出所有元素的操作。如果要写代码,请用go语言。
福大大架构师每日一题
2024/04/25
1200
文心一言 VS 讯飞星火 VS chatgpt (241)-- 算法导论17.3 7题
剑指offer 第十二天
58.对称的二叉树 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。 /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution {
10JQKA
2018/05/09
5910
每日刷题(有效括号序列,滑动窗口最大值,最小的K个数,寻找第K大)
给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列 括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。
用户11369558
2024/11/25
930
每日刷题(有效括号序列,滑动窗口最大值,最小的K个数,寻找第K大)
更适合中国程序员体质的 AI 代码助手
虽然优化非编码任务的时间分配能够带来一定程度的效率提升,但要实现研发效率的质的飞跃,关键在于提高编码阶段的效率。只有让程序员在单位时间内能产出更多的代码,他们的创造力和生产力才能得到充分的发挥。
不惑
2024/08/05
5000
更适合中国程序员体质的 AI 代码助手
推荐阅读
相关推荐
每日算法题:Day 31(Linux)
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验