滑动窗口中位数

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

例如:

[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 始终小于输入的非空数组的元素个数.

解题思想

题目会给一个数组,和一个滑动窗口的大小K,让你找出当这个窗口滑动的过程中,这个K的窗口内的中位数分别是多少?

最naive的方式就是在k个窗口内排序就好,这里不解释(因为开销很大啊,(n-k+1) * (k*log(k))。。

这里的方法是使用两个优先队列,即出队列的顺序是按照某种排好序的方式进行的。

所以我们设立两个优先队列,这里叫做堆吧:

1、最大堆,值大的先出来

2、最小堆:值小的先出来

那么回到我们的问题,我们想想如何确定中位数:

1、假设我们有上述最大堆,最小堆

2、如果我们把进入的所有值较小的一半放到最大堆,较大的一半放到最小堆中,那么较小的那一半poll出来的,和较大那一半poll出来的,不正好是k个窗口的中位数的候选值么?

3、按照上面那个思想,我们就行动,再输入值得时候,根据其大小,放入最大堆或者最小堆中,然后调整一些大小,保证最大堆那边的大小等于或者多一个于最小堆

4、当输出的时候,也就是从最大堆取一个,或者双方各取一个就可以计算了

5、删除的时候,在对应的堆中删除,再按照3中的方式更新下就好

 import java.util.Collections;
import java.util.PriorityQueue; public class Solution {
public double[] medianSlidingWindow(int[] nums, int k) {
int n = nums.length;
int m = n - k + 1;
// 结果的尺寸
double[] res = new double[m];
//两个堆,一个最大堆,一个最小
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, Collections.reverseOrder());
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(k);
for (int i = 0; i<n; i++){
int num = nums[i];
// 让maxHeap始终保存小于一半的值,minHeap保存大于一半的,正好两半
if( maxHeap.size() == 0 || maxHeap.peek() >= num) maxHeap.add(num);
else minHeap.add(num);
// 维护两个堆,保证两个堆得大小,要么保持一致(偶数时),要么maxHeap多一个(奇数时)
if( minHeap.size() > maxHeap.size() ) maxHeap.add(minHeap.poll());
if( maxHeap.size() > minHeap.size() + 1 ) minHeap.add(maxHeap.poll());
// 如果需要输出
if ( i-k+1 >=0 ){
if( k % 2 == 1 ) res[i- k + 1] = maxHeap.peek();
else res[i- k + 1] = (maxHeap.peek()/2.0 + minHeap.peek()/2.0);
// 小心溢出
// 移除并更新
int toBeRemove = nums[i - k + 1];
if( toBeRemove <= maxHeap.peek()) maxHeap.remove(toBeRemove);
else minHeap.remove(toBeRemove);
// 维护两个堆,保证两个堆得大小,要么保持一致(偶数时),要么maxHeap多一个(奇数时)
if( minHeap.size() > maxHeap.size() ) maxHeap.add(minHeap.poll());
if( maxHeap.size() > minHeap.size() + 1 ) minHeap.add(maxHeap.poll());
}
}
return res;
}
}

Leetcode 480.滑动窗口中位数的更多相关文章

  1. Java实现 LeetCode 480 滑动窗口中位数

    480. 滑动窗口中位数 中位数是有序序列最中间的那个数.如果序列的大小是偶数,则没有最中间的数:此时中位数是最中间的两个数的平均数. 例如: [2,3,4],中位数是 3 [2,3],中位数是 (2 ...

  2. LeetCode295-Find Median from Data Stream && 480. 滑动窗口中位数

    中位数是有序列表中间的数.如果列表长度是偶数,中位数则是中间两个数的平均值. 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.5 设计一个支持以下两种操 ...

  3. 【LeetCode】480. 滑动窗口中位数 Sliding Window Median(C++)

    作者: 负雪明烛 id: fuxuemingzhu 公众号: 每日算法题 本文关键词:LeetCode,力扣,算法,算法题,滑动窗口,中位数,multiset,刷题群 目录 题目描述 题目大意 解题方 ...

  4. 【Leetcode 二分】 滑动窗口中位数(480)

    题目 中位数是有序序列最中间的那个数.如果序列的大小是偶数,则没有最中间的数:此时中位数是最中间的两个数的平均数. 例如: [2,3,4],中位数是 3 [2,3],中位数是 (2 + 3) / 2 ...

  5. [LeetCode] Sliding Window Median 滑动窗口中位数

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

  6. 【leetcode 239. 滑动窗口最大值】解题报告

    思路:滑动窗口的思想,只要是求连续子序列或者子串问题,都可用滑动窗口的思想 方法一: vector<int> maxSlidingWindow(vector<int>& ...

  7. Leetcode 239.滑动窗口最大值

    滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: ...

  8. leetcode 239. 滑动窗口最大值(python)

    1. 题目描述 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示 ...

  9. leetcode全部滑动窗口题目总结C++写法(完结)

    3. 无重复字符的最长子串 A: 要找最长的无重复子串,所以用一个map保存出现过的字符,并且维持一个窗口,用le和ri指针标识.ri为当前要遍历的字符,如果ri字符在map中出现过,那么将le字符从 ...

随机推荐

  1. 织梦list/arclist标签调用文章内容

    list标签: 1. 进入后台->模型表单-> 频道模型 -> 内容模型管理 -> 修改对应的模型 2. 列表附加字段-填写body 3. 调用时添加“addfields='b ...

  2. ae(ArcEngine) java swing开发入门系列(2):ae的类型转换和Proxy类说明

    做过C#版ae的都知道,操作同一个“对象”,用他的不同功能要转换到相应的接口,但java版有时不能直接做类型转换 例如下图在C#是可以的 但在java不行,这样转会报错,看IFeatureClass的 ...

  3. copyout函数

    copyout Kernel Service   Purpose Copies data between user and kernel memory. Syntax #include <sys ...

  4. sizeof(int)

    sizeof()操作符检测的是系统为后面()中的类型.变量等分配的内存空间的字节数,这里()中是int,就是求系统为int类型的变量分配几个字节. 在16位int平台下是2:在32位int平台下是4: ...

  5. SQL_关联映射

    关联映射:一对多/多对一 存在最普遍的映射关系,简单来讲就如球员与球队的关系: 一对多:从球队角度来说一个球队拥有多个球员 即为一对多 多对一:从球员角度来说多个球员属于一个球队 即为多对一 数据表间 ...

  6. 安装指定版本的minikube

    Minikube是什么? Kubernetes集群的安装和部署对于很多初学者来说是一道坎.为了方便大家开发和体验Kubernetes,Kubernetes开源社区提供了可以在本地部署的Minikube ...

  7. HDU 4738 Caocao's Bridges taijan (求割边,神坑)

    神坑题.这题的坑点有1.判断连通,2.有重边,3.至少要有一个人背*** 因为有重边,tarjan的时候不能用子结点和父节点来判断是不是树边的二次访问,所以我的采用用前向星存边编号的奇偶性关系,用^1 ...

  8. Vue中使用computed与watch结合实现数据变化监听

    目的:当数据变化时,为其中重要数据增加边框,实现闪烁以达到提醒目的.数据格式如下,只有在未处理火警/故障时增加闪烁边框.可以使用watch进行深度监听.数据格式已定,也非常明确要监听的数据是有两个.既 ...

  9. Windows 漏洞利用开发

    第一阶段:简单栈溢出 分析栈溢出原理 寻找溢出点,了解pattern_create和pattern_offset计算溢出点的原理 寻找JMP ESP跳板,分析利用JMP ESP跳板劫持程序流的原理 编 ...

  10. Django 模板函数

    Django 模板函数 在模板中的函数是只需要函数名,不用加括号,自动执行 在前端中的函数 不用加括号,函数自动执行 前端 {% for item in userinfo.keys %} <h3 ...