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. Java字节流Stream的使用,创建方法

    首先:FileOutputStream写入数据文件 学习父类的方法 使用子类的对象 步骤: 1:子类中的构造方法   作用  :绑定输出的目的地 FileOutputStream fos= new F ...

  2. asp.net mvc areas

    http://www.codeproject.com/Articles/714356/Areas-in-ASP-NET-MVC

  3. 解决VMware下CentOS连不上网络问题

    https://blog.csdn.net/wangmx1993328/article/details/80897533

  4. Python爬虫使用MD5加密的坑

    由于公司的业务需要,需要爬取很多的国外网站图片,然后兄弟我一路正则杀过去,总共匹配到658张链接,心里美滋滋开始写下载的代码.然后就有了这次坑的记录. 首先这是我查到的链接数量 然后爬虫跑完后,美滋滋 ...

  5. Lattice Constants and Crystal Structures of some Semiconductors

    Lattice Constants and Crystal Structures of some Semiconductors and Other Materials Element or Compo ...

  6. eclipse中没有tomcat小猫

    安装了tomcat,按网上的说明也使用了tomcatPluginV331 配置文件,还是没有小猫,后来我发现,网上的tomcatPluginV331 针对eclipse 4.4版本,所以应该是插件的版 ...

  7. axios介绍

    原文地址:lewis1990@amoy axios 基于promise用于浏览器和node.js的http客户端 特点 支持浏览器和node.js 支持promise 能拦截请求和响应 能转换请求和响 ...

  8. vue 登录前做校验this.$router.push(location)

    有很多按钮在执行跳转之前,还会执行一系列方法,这时可以使用 this.$router.push(location) 来修改 url,完成跳转 例如:登录按钮,点击时需要先判断验证码等是否正确,此时

  9. POJ 1684 Corn Fields(状压dp)

    描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ ...

  10. [剑指Offer]12-矩阵中的路径(回溯)

    题目链接 https://www.nowcoder.com/practice/c61c6999eecb4b8f88a98f66b273a3cc?tpId=13&tqId=11218&t ...