leetcode中两道关于中位数的题295和480

来源:互联网 发布:开源cms系统 php商城 编辑:程序博客网 时间:2024/05/16 16:02

两道题的思路是一样的,都是建立2个堆,一个是最小堆,一个是最大堆

295题

/* * Design a data structure that supports the following two operations:void addNum(int num) - Add a integer number from the data stream to the data structure.double findMedian() - Return the median of all elements so far. * */import java.util.Comparator;import java.util.PriorityQueue;//方法类似与480题的sliding window median /*     Use two Heaps to store numbers. maxHeap for numbers smaller than current * median, minHeap for numbers bigger than and equal to current median. A * small trick I used is always make size of minHeap equal (when there are * even numbers) or 1 element more (when there are odd numbers) than the * size of maxHeap*/public class MedianFinder {public static void main(String[] args) {// TODO 自动生成的方法存根MedianFinder mf = new MedianFinder();mf.addNum(1);mf.addNum(2);System.out.println(mf.findMedian());mf.addNum(3);System.out.println(mf.findMedian());}PriorityQueue<Integer> minHeap;//使minHeap中的个数等于或者比maxHeap多1,这样对于返回中位数操作就相对简单PriorityQueue<Integer> maxHeap;public MedianFinder() {this.minHeap = new PriorityQueue<>();this.maxHeap = new PriorityQueue<>(new Comparator<Integer>() {public int compare(Integer o1, Integer o2) {return o2.compareTo(o1);}});}public void addNum(int num) {if (num < findMedian())maxHeap.add(num);elseminHeap.add(num);if (maxHeap.size() > minHeap.size())minHeap.add(maxHeap.poll());if (minHeap.size() - maxHeap.size() > 1)maxHeap.add(minHeap.poll());}public double findMedian() {if (minHeap.isEmpty() && maxHeap.isEmpty())return 0;if (minHeap.size() == maxHeap.size())return ((double) minHeap.peek() + (double) maxHeap.peek()) / 2.0;elsereturn (double) minHeap.peek();}}


480提,其实就是在295的基础上增加了一个窗口k以及一个remove函数

import java.util.ArrayList;import java.util.Arrays;import java.util.Comparator;import java.util.List;import java.util.PriorityQueue;/* * 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.5Given 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]      6Therefore, return the median sliding window as [1,-1,-1,3,5,6]. * */public class Solution {public static void main(String[] args) {// TODO 自动生成的方法存根//int[] nums = { 1, 4, 2, 3 };//double[] res = Solution.medianSlidingWindow(nums, 4);//for (double dd : res)//System.out.println(dd);}// TLE超时public static double[] medianSlidingWindow2(int[] nums, int k) {int len = nums.length;if (len == 0 || k == 0)return new double[0];List<Double> list = new ArrayList<>();double[] window = new double[k];double[] windowCopy = new double[k];for (int i = 0; i < len && i + k <= len; ++i) {for (int j = i; j < i + k; ++j) {window[j - i] = nums[j];windowCopy[j - i] = window[j - i];}Arrays.sort(windowCopy);if (k % 2 != 0)list.add(windowCopy[k / 2]);elselist.add((windowCopy[k / 2 - 1] + windowCopy[k / 2]) / 2);}double[] res = new double[list.size()];for (int i = 0; i < list.size(); ++i)res[i] = list.get(i);return res;}
/* * Use two Heaps to store numbers. maxHeap for numbers smaller than current * median, minHeap for numbers bigger than and equal to current median. A * small trick I used is always make size of minHeap equal (when there are * even numbers) or 1 element more (when there are odd numbers) than the * size of maxHeap. Then it will become very easy to calculate current * median. Keep adding number from the right side of the sliding window and * remove number from left side of the sliding window. And keep adding * current median to the result. *///2个堆加起来节点个数为k个PriorityQueue<Integer> minHeap = new PriorityQueue<>();PriorityQueue<Integer> maxHeap = new PriorityQueue<>(new Comparator<Integer>() {public int compare(Integer o1, Integer o2) {return o2.compareTo(o1);}});public double[] medianSlidingWindow(int[] nums, int k) {int n = nums.length - k + 1;double[] res = new double[n];if (n <= 0)return new double[0];for (int i = 0; i <= nums.length; ++i) {if (i >= k) {res[i - k] = getMedian();remove(nums[i - k]);}if (i < nums.length)add(nums[i]);}return res;}public void add(int num) {if (num < getMedian()) {maxHeap.add(num);} elseminHeap.add(num);if (maxHeap.size() > minHeap.size())minHeap.add(maxHeap.poll());if (minHeap.size() - maxHeap.size() > 1)maxHeap.add(minHeap.poll());}public void remove(int num) {if (num < getMedian()) {maxHeap.remove(num);} elseminHeap.remove(num);if (maxHeap.size() > minHeap.size())minHeap.add(maxHeap.poll());if (minHeap.size() - maxHeap.size() > 1)maxHeap.add(minHeap.poll());}public double getMedian() {if (minHeap.isEmpty() && maxHeap.isEmpty())return 0;if (maxHeap.size() == minHeap.size())return ((double) maxHeap.peek() + (double) minHeap.peek()) / 2.0;elsereturn (double) minHeap.peek();}}