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 array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k
numbers in the window. Each time the sliding window moves right by one
position. Your job is to output the median array for each window in the
original array.

For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.

Window position                Median
--------------- -----
[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

Therefore, return the median sliding window as [1,-1,-1,3,5,6].

Note:
You may assume k is always valid, ie: k is always smaller than input array's size for non-empty array.

Idea 1: BruteForce, keep the window sorted, if it's even numbers in the window, median = nums[(k-1)/2]/2.0 + nums[k/2]/2.0 to avoid overflow, median = nums[k/2] = nums[(k-1)/2] if k is odd, hence the formula is suitable for both even or odd k.
median = nums[(k-1)/2]/2.0 + nums[k/2]/2.0
 
Time complexity: O(nk), it takes O(k) to remove outside window element and add new element while keeping window sorted
Space complexity: O(k)
 class Solution {
public double[] medianSlidingWindow(int[] nums, int k) {
if(k > nums.length) {
return new double[0];
} double[] result = new double[nums.length - k + 1]; int[] buffer = Arrays.copyOf(nums, k);
Arrays.sort(buffer);
result[0] = buffer[(k-1)/2]/2.0 + buffer[k/2]/2.0; for(int right = k; right < nums.length; ++right) {
int pos = Arrays.binarySearch(buffer, nums[right-k]);
while(pos > 0 && buffer[pos-1] > nums[right]) {
buffer[pos] = buffer[pos-1];
--pos;
} while(pos + 1 < k && buffer[pos+1] < nums[right]) {
buffer[pos] = buffer[pos+1];
++pos;
} buffer[pos] = nums[right];
result[right - k + 1] = buffer[(k-1)/2]/2.0 + buffer[k/2]/2.0;
}
return result;
}
}

python:

 class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
window = sorted(nums[0:k]) medianIndex = k
result = []
result.append(window[(k-1)//2]/2.0 + window[k//2]/2.0) for right in range(k, len(nums)):
window.remove(nums[right-k])
bisect.insort(window, nums[right])
result.append(window[(k-1)//2]/2.0 + window[k//2]/2.0) return result

Idea 2. a. Similar to find median from Data Stream LT295, besides we need to add element to the window, we need to remove element outside of window, the removing action in priority queue in java takes O(n), unless we make customized heap-based priority queue, the alternative choice is TreeSet, to deal with duplicates, use the index for equal elements.

Time complexity: O(nlogk)

Space complexity: O(k)

 class Solution {
public double[] medianSlidingWindow(int[] nums, int k) {
if(k > nums.length) {
return new double[0];
} double[] result = new double[nums.length - k + 1]; Comparator<Integer> cmp = (a, b) -> {
if(nums[a] == nums[b]) {
return a-b;
}
return Integer.compare(nums[a], nums[b]);
};
TreeSet<Integer> maxHeap = new TreeSet<>(cmp);
TreeSet<Integer> minHeap = new TreeSet<>(cmp); for(int right = 0; right < nums.length; ++right) {
maxHeap.add(right);
minHeap.add(maxHeap.pollLast()); if(maxHeap.size() < minHeap.size()) {
maxHeap.add(minHeap.pollFirst());
} if(right >= k-1) {
if(k%2 == 1) {
result[right-k+1] = nums[maxHeap.last()];
}
else {
result[right-k+1] = nums[maxHeap.last()]/2.0 + nums[minHeap.first()]/2.0;
} if(!maxHeap.remove(right-k+1)) {
minHeap.remove(right-k+1);
}
}
} return result;
}
}

Idea 2.b priority queue

Time complexity: O(nk)

Space complexity: O(k)

 class Solution {
public double[] medianSlidingWindow(int[] nums, int k) {
if(k > nums.length) {
return new double[0];
} double[] result = new double[nums.length - k + 1]; PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
PriorityQueue<Integer> minHeap = new PriorityQueue<>(); for(int right = 0; right < nums.length; ++right) {
maxHeap.add(nums[right]);
minHeap.add(maxHeap.poll()); if(maxHeap.size() < minHeap.size()) {
maxHeap.add(minHeap.poll());
} if(right >= k-1) {
if(k%2 == 1) {
result[right-k+1] = maxHeap.peek();
}
else {
result[right-k+1] = maxHeap.peek()/2.0 + minHeap.peek()/2.0;
} if(!maxHeap.remove(nums[right-k+1])) {
minHeap.remove(nums[right-k+1]);
}
}
} return result;
}
}

Idea 2.c. priority queue + hashmap to store elements outside of window, instead of remove elemnts immediately

Time complexity: O(nlogk)

Space complexity: O(n)

 class Solution {
public double[] medianSlidingWindow(int[] nums, int k) {
if(k > nums.length) {
return new double[0];
} double[] result = new double[nums.length - k + 1]; int leftCnt = 0;
int rightCnt = 0;
Map<Integer, Integer> record = new HashMap<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
PriorityQueue<Integer> minHeap = new PriorityQueue<>(); for(int right = 0; right < nums.length; ++right) {
maxHeap.add(nums[right]);
minHeap.add(maxHeap.poll()); if(maxHeap.size() -leftCnt < minHeap.size() - rightCnt) {
maxHeap.add(minHeap.poll());
} if(right >= k-1) {
if(k%2 == 1) {
result[right-k+1] = maxHeap.peek();
}
else {
result[right-k+1] = maxHeap.peek()/2.0 + minHeap.peek()/2.0;
} if(maxHeap.peek() >= nums[right-k+1]) {
if(maxHeap.peek() == nums[right-k+1]) {
maxHeap.poll();
}
else {
record.put(nums[right-k+1], record.getOrDefault(nums[right-k+1], 0) + 1);
++leftCnt;
}
}
else {
if(minHeap.peek() == nums[right-k+1]) {
minHeap.poll();
}
else {
++rightCnt;
record.put(nums[right-k+1], record.getOrDefault(nums[right-k+1], 0) + 1);
}
} while(record.containsKey(maxHeap.peek())) {
int key = maxHeap.poll();
record.put(key, record.get(key)-1);
if(record.get(key) == 0) {
record.remove(key);
}
--leftCnt;
} while(record.containsKey(minHeap.peek())) {
int key = minHeap.poll();
record.put(key, record.get(key)-1);
if(record.get(key) == 0) {
record.remove(key);
}
--rightCnt;
}
}
} return result;
}
}

Sliding Window Median LT480的更多相关文章

  1. [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 ...

  2. 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 ...

  3. LeetCode 480. Sliding Window Median

    原题链接在这里:https://leetcode.com/problems/sliding-window-median/?tab=Description 题目: Median is the middl ...

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

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

  5. LintCode "Sliding Window Median" & "Data Stream Median"

    Besides heap, multiset<int> can also be used: class Solution { void removeOnly1(multiset<in ...

  6. Lintcode360 Sliding Window Median solution 题解

    [题目描述] Given an array of n integer, and a moving window(size k), move the window at each iteration f ...

  7. 滑动窗口的中位数 · Sliding Window Median

    [抄题]: 给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中滑动这个窗口,找到数组中每个窗口内的中位数.(如果数组个数是偶数,则在该窗口排序数字后,返回第 N/2 个数字 ...

  8. Sliding Window Median

    Description Given an array of n integer, and a moving window(size k), move the window at each iterat ...

  9. 480 Sliding Window Median 滑动窗口中位数

    详见:https://leetcode.com/problems/sliding-window-median/description/ C++: class Solution { public: ve ...

随机推荐

  1. NO_DATA_FOUND ORACL NVL函数,当第一个为空时显示第二个参数值

    ORA-01403: no data foundORA-06512: at "STG.SAP_SO_QM_CUSTOMER_ADDBOM", line 50 NVL函数的格式如下: ...

  2. CSSの変数を使う

    この文章はhttps://developer.mozilla.org/ja/docs/Web/CSS/Using_CSS_variablesを参考します. これは実験段階の機能です.この機能は複数のブ ...

  3. python学习day6 for循环 字符串的内置方法

    1.for循环 和while相比 l=[1,2,3] i=0 while i <len(l) print(l[i]) i+=1 l=['a','b','c'] for item in l: pr ...

  4. 前端基础之css介绍

    CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). CSS语法 CSS实例 ...

  5. c++中的类(class)-----笔记(类多态)

    1,多态是一种运行期绑定机制,通过这种机制,实现将函数名绑定到函数具体实现代码的目的.一个函数的名称与其入口地址是紧密相连的,入口地址是该函数在内存中的起始地址.如果对一个函数的绑定发生在运行时刻而非 ...

  6. 牛客网练习赛43-C(图论)

    题目链接:https://ac.nowcoder.com/acm/contest/548/C 题意:有n个知识点,学会每个知识点花T[i],已经学会了其中k个知识点,有m组关系,t1,t2,t3,表示 ...

  7. avcodec_decode_video2少帧问题

    使用libav转码视频时发现一个问题:使用下面这段代码解码视频时,解码中会不时丢掉几帧. ){ ret = avcodec_decode_video2(video_dec_ctx, vframe, & ...

  8. Ant 之 Task

    Ant提供了大量的核心task和可选task,除此之外,Ant还允许用户定义自己的task,这大大扩展了Ant的功能.本书由于篇幅关系,所以不可能详细介绍Ant所有的核心task和可选task,本书将 ...

  9. JTAG-测试数据寄存器

    1.问题:JTAG中的数据寄存器的结构 JTAG标准规定了两个必须的数据寄存器: 1.旁通寄存器 2.边界扫描寄存器(已经在可测性设计-扫描通路中介绍了) 可选的的寄存器有: 1.器件标示寄存器(32 ...

  10. Linux sudo用法与配置

    Linux环境:CentOS 6.7 结构说明 可以通过编辑文件/etc/sudoers来配置,通常使用visudo命令来进行修改,因为如果你修改的格式不符合它会进行提示.接下来就通过一个格式来了解它 ...