滑动窗口中位数

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

例如:

[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. 织梦DeDeCMS友情链接文字显示不全

    文件:/include/taglib/flink.lib.php 把下面代码中的24改为合适的值 $attlist=”type|textall,row|24,titlelen|24,linktype| ...

  2. VC++堆栈大小设置

    VC++堆栈默认大小是1M,如果你分配大于1M的堆,一般会出异常,这里你要把堆调大些,下面是VC++6.0与VC++2010的设置方法 VC++6.0: 工程==>设置==>“连接”界面, ...

  3. ZOJ 3471 Most Powerful (状压DP,经典)

    题意: 有n个原子,每当两个原子碰撞时就会产生能量,并且消耗其中一个原子.已知每两个原子碰撞时消耗其中指定一个原子所产生的能量,问最多能产生多少能量? 思路: 一开始以为是找一个有序序列,使得能量最大 ...

  4. python基础教程总结6——类

    1. 如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class  ...

  5. Linux 的数字权限意义

    三个组 每个都有三个权限 r w x每个权限用二进制 0 和 1 标示 1即为有此权限 0 标示无权限  ower    group  other  r w x    r w x  r w x 每个组 ...

  6. MovieReview—Wile Hunter(荒野猎人)

     Faith is Power         Faith is power, this sentence is not wrong. Find your own beliefs, and strug ...

  7. Oracle 11g 新特性 – HM(Hang Manager)简介

    在这篇文章中我们会对oracle 11g 新特性—hang 管理器(Hang Manager) 进行介绍.我们需要说明,HM 只在RAC 数据库中存在. 在我们诊断数据库问题的时候,经常会遇到一些数据 ...

  8. UVA 1599, POJ 3092 Ideal Path 理想路径 (逆向BFS跑层次图)

    大体思路是从终点反向做一次BFS得到一个层次图,然后从起点开始依次向更小的层跑,跑的时候选则字典序最小的,由于可能有多个满足条件的点,所以要把这层满足条件的点保存起来,在跑下一层.跑完一层就会得到这层 ...

  9. UVA 1616 Caravan Robbers 商队抢劫者(二分)

    x越大越难满足条件,二分,每次贪心的选区间判断是否合法.此题精度要求很高需要用long double,结果要输出分数,那么就枚举一下分母,然后求出分子,在判断一下和原来的数的误差. #include& ...

  10. VC++:鼠标的使用

    长期改变鼠标形状: SetClassLongPtr(GetSafeHwnd(), GCLP_HCURSOR, (LONG)LoadCursor(NULL, IDC_WAIT));//这个是x64下可以 ...