LeetCode 480. 滑动窗口中位数 我就是我 2022-10-27 01:45 101阅读 0赞 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODE5OTc3MA_size_16_color_FFFFFF_t_70] [官方题解][Link 1] class Solution { public double[] medianSlidingWindow(int[] nums, int k) { DualHeap dh = new DualHeap(k); for (int i = 0; i < k; ++i) { dh.insert(nums[i]); } double[] ans = new double[nums.length - k + 1]; ans[0] = dh.getMedian(); for (int i = k; i < nums.length; ++i) { dh.insert(nums[i]); dh.erase(nums[i - k]); ans[i - k + 1] = dh.getMedian(); } return ans; } } class DualHeap { // 大根堆,维护较小的一半元素 private PriorityQueue<Integer> small; // 小根堆,维护较大的一半元素 private PriorityQueue<Integer> large; // 哈希表,记录「延迟删除」的元素,key 为元素,value 为需要删除的次数 private Map<Integer, Integer> delayed; private int k; // small 和 large 当前包含的元素个数,需要扣除被「延迟删除」的元素 private int smallSize, largeSize; public DualHeap(int k) { this.small = new PriorityQueue<Integer>(new Comparator<Integer>() { public int compare(Integer num1, Integer num2) { return num2.compareTo(num1); } }); this.large = new PriorityQueue<Integer>(new Comparator<Integer>() { public int compare(Integer num1, Integer num2) { return num1.compareTo(num2); } }); this.delayed = new HashMap<Integer, Integer>(); this.k = k; this.smallSize = 0; this.largeSize = 0; } public double getMedian() { return (k & 1) == 1 ? small.peek() : ((double) small.peek() + large.peek()) / 2; } public void insert(int num) { if (small.isEmpty() || num <= small.peek()) { small.offer(num); ++smallSize; } else { large.offer(num); ++largeSize; } makeBalance(); } public void erase(int num) { delayed.put(num, delayed.getOrDefault(num, 0) + 1); if (num <= small.peek()) { --smallSize; if (num == small.peek()) { prune(small); } } else { --largeSize; if (num == large.peek()) { prune(large); } } makeBalance(); } // 不断地弹出 heap 的堆顶元素,并且更新哈希表 private void prune(PriorityQueue<Integer> heap) { while (!heap.isEmpty()) { int num = heap.peek(); if (delayed.containsKey(num)) { delayed.put(num, delayed.get(num) - 1); if (delayed.get(num) == 0) { delayed.remove(num); } heap.poll(); } else { break; } } } // 调整 small 和 large 中的元素个数,使得二者的元素个数满足要求 private void makeBalance() { if (smallSize > largeSize + 1) { // small 比 large 元素多 2 个 large.offer(small.poll()); --smallSize; ++largeSize; // small 堆顶元素被移除,需要进行 prune prune(small); } else if (smallSize < largeSize) { // large 比 small 元素多 1 个 small.offer(large.poll()); ++smallSize; --largeSize; // large 堆顶元素被移除,需要进行 prune prune(large); } } } [另一个题解耗时比较慢但比较好理解,也是双优先队列][Link 2] class Solution { public static double[] medianSlidingWindow(int[] nums, int k) { if (nums == null || nums.length == 0) { return new double[]{ }; } double[] res = new double[nums.length - k + 1]; PriorityQueue<Double> maxHeap = new PriorityQueue<>(Collections.reverseOrder()); PriorityQueue<Double> minHeap = new PriorityQueue<>(); //滑动窗口固定写法 int i = 0, j = 0; int count = 0; int index = 0; //res的下标 for (i = 0; i < nums.length - k + 1; i++) { while (j < nums.length && count < k) { add(maxHeap, minHeap, nums[j]); count++; j++; } if (count == k) { if (maxHeap.size() == minHeap.size()) { res[index++] = (maxHeap.peek() + minHeap.peek()) * 0.5; //这边给[2147483647,2147483647],这就越界了,用long~ } else { res[index++] = maxHeap.peek(); } } count--; remove(maxHeap, minHeap, (double)nums[i]); } return res; } public static void add(PriorityQueue<Double> maxHeap, PriorityQueue<Double> minHeap, double num) { maxHeap.offer((double)num); minHeap.offer(maxHeap.poll()); if (minHeap.size() > maxHeap.size()) { maxHeap.offer(minHeap.poll()); } return; } public static void remove(PriorityQueue<Double> maxHeap, PriorityQueue<Double> minHeap, double del) { if (del <= maxHeap.peek()) { maxHeap.remove(del); } else { minHeap.remove(del); } return; } } [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODE5OTc3MA_size_16_color_FFFFFF_t_70]: /images/20221024/d92071a5cedd42bba0e65678c4efe90e.png [Link 1]: https://leetcode-cn.com/problems/sliding-window-median/solution/hua-dong-chuang-kou-zhong-wei-shu-by-lee-7ai6/ [Link 2]: https://leetcode-cn.com/problems/sliding-window-median/solution/dui-295ti-shao-zuo-gai-jin-by-jerry_nju/
还没有评论,来说两句吧...