一、题目
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[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)