Leetcode 480.滑动窗口中位数

滑动窗口中位数

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

例如:

[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中的方式更新下就好

 1 import java.util.Collections;
 2 import java.util.PriorityQueue;
 3
 4 public class Solution {
 5     public double[] medianSlidingWindow(int[] nums, int k) {
 6         int n = nums.length;
 7         int m = n - k + 1;
 8         // 结果的尺寸
 9         double[] res = new double[m];
10         //两个堆,一个最大堆,一个最小
11         PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, Collections.reverseOrder());
12         PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(k);
13         for (int i = 0; i<n; i++){
14             int num = nums[i];
15             // 让maxHeap始终保存小于一半的值,minHeap保存大于一半的,正好两半
16             if( maxHeap.size() == 0 || maxHeap.peek() >= num) maxHeap.add(num);
17             else minHeap.add(num);
18             // 维护两个堆,保证两个堆得大小,要么保持一致(偶数时),要么maxHeap多一个(奇数时)
19             if( minHeap.size() > maxHeap.size() ) maxHeap.add(minHeap.poll());
20             if( maxHeap.size() > minHeap.size() + 1 ) minHeap.add(maxHeap.poll());
21             // 如果需要输出
22             if ( i-k+1 >=0 ){
23                 if( k % 2 == 1 ) res[i- k + 1] = maxHeap.peek();
24                 else res[i- k + 1] = (maxHeap.peek()/2.0 + minHeap.peek()/2.0);
25                 // 小心溢出
26                 // 移除并更新
27                 int toBeRemove = nums[i - k + 1];
28                 if( toBeRemove <= maxHeap.peek()) maxHeap.remove(toBeRemove);
29                 else minHeap.remove(toBeRemove);
30                 // 维护两个堆,保证两个堆得大小,要么保持一致(偶数时),要么maxHeap多一个(奇数时)
31                 if( minHeap.size() > maxHeap.size() ) maxHeap.add(minHeap.poll());
32                 if( maxHeap.size() > minHeap.size() + 1 ) minHeap.add(maxHeap.poll());
33             }
34         }
35         return res;
36     }
37 }

原文地址:https://www.cnblogs.com/kexinxin/p/10372465.html

时间: 2024-08-29 02:36:53

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

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

题目 中位数是有序序列最中间的那个数.如果序列的大小是偶数,则没有最中间的数:此时中位数是最中间的两个数的平均数. 例如: [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. 窗口位

[Swift]LeetCode480. 滑动窗口中位数 | Sliding Window Median

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. Examples: [2,3,4] , the median is 3 [2,3], the median is (2 + 3) / 2 = 2.5 Given an a

leetcode 239. 滑动窗口最大值(单调队列)

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 进阶: 你能在线性时间复杂度内解决此题吗? 示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值--------------- -----[1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6

leetcode ---双指针+滑动窗口

一:Minimum Size Subarray Sum 题目: Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return 0 instead. For example, given the array [2,3,1,2,4,3] and s = 7, th

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

思路:滑动窗口的思想,只要是求连续子序列或者子串问题,都可用滑动窗口的思想 方法一: vector<int> maxSlidingWindow(vector<int>& nums, int k) { vector<int> res; if (nums.size()==0) return res; int i=0; deque<int> dq; for (i=0;i<nums.size();++i) { while(!dq.empty()&

Leetcode 239. 滑动窗口最大值

class Solution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { vector<int> ret; if(nums.size()==0) return ret; deque<int> q; for(int i=0; i<nums.size(); ++i) { if(q.empty() || nums[q.back()] > nums[i] )

堆的相关题目—滑动窗口

1.数据流滑动窗口平均值 描述 给出一串整数流和窗口大小,计算滑动窗口中所有整数的平均值. 样例 样例1 : MovingAverage m = new MovingAverage(3); m.next(1) = 1 // 返回 1.00000 m.next(10) = (1 + 10) / 2 // 返回 5.50000 m.next(3) = (1 + 10 + 3) / 3 // 返回 4.66667 m.next(5) = (10 + 3 + 5) / 3 // 返回 6.00000来源

滑动窗口的中位数

2017年8月7日 19:46:26 难度:困难 描述:给定一个包含 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],

算法-滑动窗口的中位数(堆)

今天在网上刷了一道关于堆的题,感觉有所收获.因为在这里之前,之前从来没有接触过关于堆的题目. 题意: 给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中 滑动这个窗口,找到数组中每个窗口内的中位数.(如果数组个数是偶数,则在 该窗口排序数字后,返回第 N/2 个数字.) 样例: 对于数组 [1,2,7,8,5], 滑动大小 k = 3 的窗口时,返回 [2,7,7] 最初,窗口的数组是这样的: [ | 1,2,7 | ,8,5] , 返回中位数 2; 接着,窗口继续向