一、题目
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
- void addNum(int num) - 从数据流中添加一个整数到数据结构中。
- double findMedian() - 返回目前所有元素的中位数。
点击查看原题
难度级别: 困难
二、思路
1)数组存数据+二分查找+线性插入
用一个ArrayList存储数据,保证其有序,每次插入进行二分查找位置,再插入进去
返回结果时,判断容量是否奇偶
2)大小根堆
用两个根堆,大根堆存储小值部分,小根堆存储大值部门,每次插入进行判断num该进入哪个堆,并做好两个堆数据容量的平衡
返回结果只需要判断两个根堆大小,来进行返回
三、代码
1)数组存数据+二分查找+线性插入
class MedianFinder {private List<Integer> nums;/** initialize your data structure here. */public MedianFinder() {nums = new ArrayList();}public void addNum(int num) {int loc = searchByBinary(num);if (loc == nums.size()) {nums.add(num);} else {nums.add(loc, num);}}private int searchByBinary(int num) {int s = 0, e = nums.size();while (s < e) {int mid = (s + e)/2;if (nums.get(mid) == num) {return mid;} else if (nums.get(mid) > num) {e = mid;} else {s = mid + 1;}}return s;}public double findMedian() {if ((nums.size() & 1) == 1) {return (double)nums.get(nums.size()/2);}return (double)((double)nums.get(nums.size()/2 - 1) + (double)nums.get(nums.size()/2 ))/2;}}
查找和插入时间复杂度O(logn+n),返回中位数时间复杂度O(1),空间复杂度为O(n)
1)数组存数据+二分查找+线性插入
class MedianFinder {private PriorityQueue<Integer> minH = new PriorityQueue(); //存高部分private PriorityQueue<Integer> maxH = new PriorityQueue<Integer>((i1, i2) -> (i2 - i1)); // 存低位/** initialize your data structure here. */public MedianFinder() {}public void addNum(int num) {if (maxH.size() == 0) {maxH.add(num);} else if (maxH.peek() <= num) {minH.add(num);if (minH.size() > maxH.size() + 1) {maxH.add(minH.poll());}} else {maxH.add(num);if (maxH.size() >= minH.size() + 1) {minH.add(maxH.poll());}}}public double findMedian() {if (maxH.size() == minH.size()) {return ((double)maxH.peek() + (double)minH.peek())/2d;}if (maxH.size() > minH.size()) {return (double)maxH.peek();}return (double)minH.peek();}}
插入时间复杂度O(logn),返回中位数时间复杂度O(1),空间复杂度为O(n)
