1. 程式人生 > >[LeetCode] Sliding Window Median

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

題解

這道題目同樣是在資料流中求取中位數,關鍵在於利用最大堆和最小堆。對於輸入的資料保持這樣兩個堆,一個最大堆maxHeap,一個最小堆minHeap,並有以下性質:1、同時maxHeap中所有的數小於等於minHeap中所有的數(這步操作可以通過先將輸入放進minHeap,再從minHeap中取出來最小數放進maxHeap實現) 2、maxHeap中元素個數大於等於minHeap中元素個數,這個性質可以通過插入,刪除資料後進行均衡來實現:

public class Solution {
    private Queue<Double> minHeap = new PriorityQueue<>();
    private
Queue<Double> maxHeap = new PriorityQueue<>(new Comparator<Double>(){ @Override public int compare(Double o1, Double o2) { if (o1 > o2) return -1; else if (o1 < o2) return 1; else return 0; } }); public double
[] medianSlidingWindow(int[] nums, int k) { int n = nums.length - k + 1; if (n <= 0) return new double[0]; double[] result = new double[n]; for (int i = 0; i <= nums.length; i++) { if (i >= k) { result[i - k] = getM(); remove(nums[i - k]); } if (i < nums.length) add(nums[i]); } return result; } private void add(int num){ //保持最大堆中元素小於最小堆中元素 minHeap.add((double)num); maxHeap.add(minHeap.poll()); //元素數目均衡操作 if (minHeap.size() > maxHeap.size()) maxHeap.add(minHeap.poll()); if (maxHeap.size() - minHeap.size() > 1) minHeap.add(maxHeap.poll()); } private void remove(int num){ double mid = getM(); double n = (double) num; if (n <= mid) { maxHeap.remove(n); } else { minHeap.remove(n); } if (maxHeap.size() < minHeap.size()) maxHeap.add(minHeap.poll()); if (maxHeap.size() - minHeap.size() > 1) minHeap.add(maxHeap.poll()); } private double getM() { if (maxHeap.isEmpty() && minHeap.isEmpty()) return 0; if (minHeap.size() == maxHeap.size()) return ((double)maxHeap.peek() + (double)minHeap.peek()) / 2.0; else return (double)maxHeap.peek(); } }