如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
数据范围:数据流中数个数满足
,大小满足 
进阶: 空间复杂度
, 时间复杂度 %20%5C)
进阶: 空间复杂度
[5,2,3,4,1,6,7,0,8]
"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
数据流里面不断吐出的是5,2,3...,则得到的平均数分别为5,(5+2)/2,3...
[1,1,1]
"1.00 1.00 1.00 "
#Python版 #该题Python版牛客有问题 #一直提示 def GetMedian(self)函数多给了一个参数 ,然后自己def GetMedian(self,n=None): #多给它加了一个默认参数,就过了。。。我擦 #思路:两个堆,自己实现,一个最大堆,一个最小堆
# -*- coding:utf-8 -*- class Solution: def __init__(self): self.minNums=[] self.maxNums=[] def maxHeapInsert(self,num): self.maxNums.append(num) lens = len(self.maxNums) i = lens - 1 while i > 0: if self.maxNums[i] > self.maxNums[(i - 1) / 2]: t = self.maxNums[(i - 1) / 2] self.maxNums[(i - 1) / 2] = self.maxNums[i] self.maxNums[i] = t i = (i - 1) / 2 else: break def maxHeapPop(self): t = self.maxNums[0] self.maxNums[0] = self.maxNums[-1] self.maxNums.pop() lens = len(self.maxNums) i = 0 while 2 * i + 1 < lens: nexti = 2 * i + 1 if (nexti + 1 < lens) and self.maxNums[nexti + 1] > self.maxNums[nexti]: nexti += 1 if self.maxNums[nexti] > self.maxNums[i]: tmp = self.maxNums[i] self.maxNums[i] = self.maxNums[nexti] self.maxNums[nexti] = tmp i = nexti else: break return t def minHeapInsert(self,num): self.minNums.append(num) lens = len(self.minNums) i = lens - 1 while i > 0: if self.minNums[i] < self.minNums[(i - 1) / 2]: t = self.minNums[(i - 1) / 2] self.minNums[(i - 1) / 2] = self.minNums[i] self.minNums[i] = t i = (i - 1) / 2 else: break def minHeapPop(self): t = self.minNums[0] self.minNums[0] = self.minNums[-1] self.minNums.pop() lens = len(self.minNums) i = 0 while 2 * i + 1 < lens: nexti = 2 * i + 1 if (nexti + 1 < lens) and self.minNums[nexti + 1] < self.minNums[nexti]: nexti += 1 if self.minNums[nexti] < self.minNums[i]: tmp = self.minNums[i] self.minNums[i] = self.minNums[nexti] self.minNums[nexti] = tmp i = nexti else: break return t def Insert(self, num): if (len(self.minNums)+len(self.maxNums))&1==0: if len(self.maxNums)>0 and num < self.maxNums[0]: self.maxHeapInsert(num) num = self.maxHeapPop() self.minHeapInsert(num) else: if len(self.minNums)>0 and num > self.minNums[0]: self.minHeapInsert(num) num = self.minHeapPop() self.maxHeapInsert(num) def GetMedian(self,n=None): allLen = len(self.minNums) + len(self.maxNums) if allLen ==0: return -1 if allLen &1==1: return self.minNums[0] else: return (self.maxNums[0] + self.minNums[0]+0.0)/2 t = Solution() t.Insert(5) print t.GetMedian() t.Insert(2) print t.GetMedian() t.Insert(3) print t.GetMedian() t.Insert(4) print t.GetMedian() t.Insert(1) print t.GetMedian() t.Insert(6) print t.GetMedian() t.Insert(7) print t.GetMedian() t.Insert(0) print t.GetMedian() t.Insert(8) print t.GetMedian()
public class Solution{ private Heap maxHeap = new Heap(Heap.isMaxHeap); private Heap minHeap = new Heap(Heap.isMinHeap); /** * 插入有两种思路: * 1:直接插入大堆中,之后若两堆尺寸之差大于1(也就是2),则从大堆中弹出堆顶元素并插入到小堆中 * 若两队之差不大于1,则直接插入大堆中即可。 * 2:奇数个数插入到大堆中,偶数个数插入到小堆中, * 但是 可能会出现当前待插入的数比小堆堆顶元素大,此时需要将元素先插入到小堆,然后将小堆堆顶元素弹出并插入到大堆中 * 对于偶数时插入小堆的情况,一样的道理。why? * 因为要保证最大堆的元素要比最小堆的元素都要小。 * @param num */ public void Insert(Integer num) { //若总尺寸为偶数,则插入大顶堆中 if(((maxHeap.si敏感词Heap.size()) & 1) == 0){ if(minHeap.size() != 0 && num > minHeap.peek()){ minHeap.add(num); maxHeap.add(minHeap.pop()); }else{ maxHeap.add(num); } }else{ if(maxHeap.size() != 0 && num < maxHeap.peek()){ maxHeap.add(num); minHeap.add(maxHeap.pop()); }else{ minHeap.add(num); } } } public Double GetMedian() { double res = 0.0; if(((maxHeap.si敏感词Heap.size()) & 1) == 0){ res = (maxHeap.peek() + minHeap.peek()) / 2.0; }else{ res = maxHeap.peek(); } return res; } } //堆类,可直接设置最大堆最小堆 class Heap { public List<Integer> list = null; public static final boolean isMaxHeap = true; public static final boolean isMinHeap = false; private boolean flag = true; //true表示最大堆,false表示最小堆 public Heap(){ this.list = new ArrayList<Integer>(); } public Heap(boolean flag){ this.list = new ArrayList<Integer>(); this.flag = flag; } //获取堆大小 public int size(){ return this.list.size(); } //获取堆顶元素 public int peek(){ if(list.size() == 0) return 0; return list.get(0); } //插入元素,从插入点开始向上调整堆 public void add(int val){ this.list.add(val); int i = list.size() - 1, index, parent, cur; while(i > 0){ index = (i - 1) / 2; parent = list.get(index); cur = list.get(i); if(flag == true && parent < cur){ swap(index, i); }else if(flag == false && parent > cur){ swap(index, i); } i = index; } } /** * 将堆顶元素取出,并重新调整堆。 * 1>取出堆顶元素 * 2>将最后一个元素放到堆顶 * 3>向下调整堆 */ public int pop(){ if(list.size() == 0) return -1; int res = list.get(0); list.set(0,list.get(list.size() - 1)); list.remove(list.size()-1); int len = list.size() - 1 , i = 0; int left , right; while(i < len){ left = (i << 1) + 1; right= (i << 1) + 2; int maxIndex = i; if(flag == true){ if(left < len && list.get(left) > list.get(maxIndex)) maxIndex = left; if(right< len && list.get(right)> list.get(maxIndex)) maxIndex = right; }else{ if(left < len && list.get(left) < list.get(maxIndex)) maxIndex = left; if(right< len && list.get(right)< list.get(maxIndex)) maxIndex = right; } if(maxIndex != i){ swap(maxIndex,i); i = maxIndex; }else break; } return res; } //交换list中两个位置的元素 public void swap(int i, int j){ int temp = list.get(i); list.set(i, list.get(j)); list.set(j,temp); } }
- 大根堆:large保存大的半数的数据
- 小根堆:small保存小的半数的数据
获取中位数的时间复杂度为O(1),插入一个数据的时间复杂度为O(log(n))
技巧:
# -*- coding:utf-8 -*-
from heapq import *
class Solution:
def __init__(self):
self.heaps = [], []
def Insert(self, num):
# write code here
small, large = self.heaps
heappush(small, -heappushpop(large, num))#将num放入大根堆,并弹出大根堆的最小值,取反,放入大根堆small
if len(large) < len(small):
heappush(large, -heappop(small)) #弹出small中最小的值,取反,即最大的值,放入large
def GetMedian(self,ss):
# write code here
small,large = self.heaps
if len(large) > len(small):
return float(large[0])
return (large[0] - small[0]) /2.0
mark版的详细解释(c++)
class Solution {
public:
void Insert(int num)
{
if(left.empty() || num <= left.top()){
left.push(num);
}else{
right.push(num);
}
// 左边大顶堆的大小最多可以比右边小顶堆大1(奇数次输入)
if(left.size() == right.size() + 2){
right.push(left.top());
left.pop();
}
// 因为最后返回的只有可能是左边大顶堆的堆顶,所以右边小顶堆的大小不能比左边小顶堆大
if(left.size() + 1 == right.size()){
left.push(right.top());
right.pop();
}
}
double GetMedian()
{
return left.size() == right.size() ? (left.top() + right.top())/2\. : left.top();
}
private:
// 右边小顶堆的元素都大于左边大顶堆的元素,并且左边元素的个数,要么与右边相等(偶数次输入),要么比右边大1(奇数次输入)
priority_queue, less > left; // 大顶堆
priority_queue, greater > right; // 小顶堆
};
最大堆和最小堆的底层实现
class Solution {
private:
vector<int> max_heap;
vector<int> min_heap;
void adjust_heap(vector<int> &nums, int lo, int hi, bool is_max) {
for (int cur = lo, next = cur * 2 + 1; next <= hi; cur = next, next = cur * 2 + 1) {
if (is_max) {
if (next < hi && nums[next + 1] > nums[next]) {
++next;
}
if (nums[next] > nums[cur]) {
swap(nums[next], nums[cur]);
} else {
break;
}
} else {
if (next < hi && nums[next + 1] < nums[next]) {
++next;
}
if (nums[next] < nums[cur]) {
swap(nums[next], nums[cur]);
} else {
break;
}
}
}
}
void build_heap(vector<int> &heap, bool is_max) {
int n = heap.size();
for (int i = n / 2 - 1; i >= 0; --i) {
adjust_heap(heap, i, n - 1, is_max);
}
}
int pop(vector<int> &heap, bool is_max) {
int ret = heap[0];
heap.erase(heap.begin());
build_heap(heap, is_max);
return ret;
}
void push(vector<int> &heap, int num, bool is_max) {
heap.emplace_back(num);
build_heap(heap, is_max);
}
public:
void Insert(int num) {
if (min_heap.empty() || num > min_heap[0]) {
push(min_heap, num, false);
} else {
push(max_heap, num, true);
}
if (min_heap.size() == max_heap.size() + 2) {
push(max_heap, pop(min_heap, false), true);
}
if (min_heap.size() + 1 == max_heap.size()) {
push(min_heap, pop(max_heap, true), false);
}
}
double GetMedian() {
return min_heap.size() == max_heap.si***_heap[0] + max_heap[0]) / 2. : min_heap[0];
}
};
private PriorityQueue<Integer> min = new PriorityQueue<Integer>(); private PriorityQueue<Integer> max = new PriorityQueue<Integer>(15,new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); } }); private int count = 0; public void Insert(Integer num) { count++; if (count % 2 == 1){ max.offer(num);//先从大顶堆过滤一遍 min.offer(max.poll()); }else { min.offer(num);//先从小顶堆过滤一遍 max.offer(min.poll()); } } public Double GetMedian() { if (count % 2 == 0) return (min.peek() + max.peek())/2.0; else return (double)min.peek(); }
// LinkedList<Integer> data = new LinkedList<Integer>(); // public void Insert(Integer num) { // for (int i = data.size() - 1; i >= 0 ; i--) { // if (num >= data.get(i)){ // data.add(i+1,num); // return; // } // } // data.addFirst(num); // } // // public Double GetMedian() { // int size = data.size(); // if (size% 2 == 1) return (double)data.get(size/2); // else return (data.get(size/2) + data.get(size/2 - 1))/2.0; // }
import java.util.Collections;
import java.util.PriorityQueue;
public class Solution {
// smaller堆用于存放相对较小的一半数字,larger堆用于存放相对较大的一半数字
// 由于默认排序堆顶是最小值,而对于smaller的一半我们更关注最大值,因此使用reverseOrder()来初始化
private PriorityQueue<Integer> smaller = new PriorityQueue<>(Collections.reverseOrder());
private PriorityQueue<Integer> larger = new PriorityQueue<>();
public void Insert(Integer num) {
// 首次将数字存入smaller,然后在将smaller中堆顶的(较小一半数字的最大值)存入larger
smaller.add(num);
larger.add(smaller.poll());
// 为了保证larger内的数量<=smaller内的数量,进行两个堆大小的比较,并进行转移
// 此规则下,如果两个堆数量相等,则中位数为两个堆顶数字的平均值;若不相等则为smaller的堆顶数字
// 也可以使larger存储更多数字,则不相等时,中位数为larger的堆顶数字
if (larger.size() > smaller.size()) {
smaller.add(larger.poll());
}
}
public Double GetMedian() {
// 如前所述,两者大小相等,则求平均
if (smaller.size() == larger.size()) {
return ((double)smaller.peek() + (double)larger.peek()) / 2;
} else { // 否则中位数为smaller的堆顶数字
return (double)smaller.peek();
}
}
}
//看大家都用堆,那我来个树,插入和取中值复杂度都是lgn public class Solution { private TreeNode root; public void Insert(Integer num) { root = Insert(root, num); } private TreeNode Insert(TreeNode node, Integer num){ if(node == null) return new TreeNode(num, 1); node.size++; if(num <= node.val) node.left = Insert(node.left, num); else node.right = Insert(node.right, num); return node; } public Double GetMedian() { if(root == null) return null; if((root.size & 1) == 0) return (double)(getKth(root, root.size/2) + getKth(root, root.size/2 + 1))/2; else return (double)getKth(root, (root.size + 1)/2); } private int getKth(TreeNode node, int k){ int size = node.left == null ? 0 : node.left.size; if(k <= size) return getKth(node.left, k); else if(k == size + 1) return node.val; else return getKth(node.right, k-size-1); } public static class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; int size = 0;//该字段的含义是以该节点为子树根的节点总个数 public TreeNode(int val, int size) { this.val = val; this.size = size; } } }
import java.util.*; public class Solution { // 代表排序后的左半部分 private PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1); // 代表排序后的右半部分 private PriorityQueue<Integer> minHeap = new PriorityQueue<>(); // 时间复杂度O(logn) public void Insert(Integer num) { // 平均分配,元素个数为奇数时插入到maxHeap,为偶数时插入到minHeap if ((minHeap.size() + maxHeap.size()) % 2 == 1) { // 若num完全小于minHeap的所有元素,直接将num插入maxHeap即可 // 若num大于minHeap中的一些元素,则将num插入minHeap, 然后移除minHeap的最小值,将其插入maxHeap if (!minHeap.isEmpty() && num > minHeap.element()) { minHeap.add(num); num = minHeap.remove(); } maxHeap.add(num); } else { // 若num完全大于maxHeap的所有元素,直接将num插入minHeap即可 // 若num小于maxHeap中的一些元素,则将num插入maxHeap,然后移除maxHeap的最大值,将其插入minHeap if (!maxHeap.isEmpty() && num < maxHeap.element()) { maxHeap.add(num); num = maxHeap.remove(); } minHeap.add(num); } } // 时间复杂度O(1) public Double GetMedian() { int size = maxHeap.size() + minHeap.size(); if (size % 2 == 1) { return minHeap.element() * 1.0; } else { return (maxHeap.element() + minHeap.element()) / 2.0; } } }
import java.util.PriorityQueue; import java.util.Comparator; public class Solution { // 初始化一个大根堆,存中位数左边的数据,一个小根堆,存中位数右边的数据 // 动态维护两个数据结构的大小,即最多只相差一个 // 因为要求的是中位数,那么这两个堆,大顶堆用来存较小的数,从大到小排列; // 小顶堆存较大的数,从小到大的顺序排序*,显然中位数就是大顶堆的根节点与小顶堆的根节点和的平均数。 // 保证:小顶堆中的元素都大于等于大顶堆中的元素,所以每次塞值,并不是直接塞进去,而是从另一个堆中poll出一个最大(最小)的塞值 // 当数目为偶数的时候,将这个值插入大顶堆中,再将大顶堆中根节点(即最大值)插入到小顶堆中; // 当数目为奇数的时候,将这个值插入小顶堆中,再讲小顶堆中根节点(即最小值)插入到大顶堆中; // 取中位数的时候,如果当前个数为偶数,显然是取小顶堆和大顶堆根结点的平均值;如果当前个数为奇数,显然是取小顶堆的根节点 // 小顶堆 private PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); // 大顶堆 private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); // 记录偶数个还是奇数个 int count = 0; // 每次插入小顶堆的是当前大顶堆中最大的数 // 每次插入大顶堆的是当前小顶堆中最小的数 // 这样保证小顶堆中的数永远大于等于大顶堆中的数 // 中位数就可以方便地从两者的根结点中获取了 public void Insert(Integer num) { // 个数为偶数的话,则先插入到大顶堆,然后将大顶堆中最大的数插入小顶堆中 if (count % 2 == 0) { maxHeap.offer(num); int max = maxHeap.poll(); minHeap.offer(max); } else { // 个数为奇数的话,则先插入到小顶堆,然后将小顶堆中最小的数插入大顶堆中 minHeap.offer(num); int min = minHeap.poll(); maxHeap.offer(min); } count++; } public Double GetMedian() { // 当前为偶数个,则取小顶堆和大顶堆的堆顶元素求平均 if (count % 2 == 0) { return new Double(minHeap.peek() + maxHeap.peek()) / 2; } else { // 当前为奇数个,则直接从小顶堆中取元素即可 return new Double(minHeap.peek()); } } }
import java.util.Arrays; public class Solution { static int[] seq = new int[0]; public static void Insert(Integer num) { // int stop = list.size(), start = 0; int stop = seq.length-1, start = 0; if(seq.length == 0){ seq = Arrays.copyOf(seq, 1); seq[0] = num; }else{ while(stop >= start){ int mid = (start+stop) >>> 1; if(seq[mid] < num){ start = mid + 1; }else if(seq[mid] > num){ stop = mid - 1; }else{ // key == mid seq = Arrays.copyOf(seq, seq.length+1); for(int i = seq.length-1;i > mid;i--){ seq[i] = seq[i-1]; } seq[mid] = num; break; } } if(start > seq.length-1){//num bigger than last key seq = Arrays.copyOf(seq, seq.length+1); seq[start] = num; }else if(stop < 0){ //num less than first key seq = Arrays.copyOf(seq, seq.length+1); for(int i = seq.length-1; i >0;i--){ seq[i] = seq[i-1]; } seq[start] = num; }else{ // num in between the seq seq = Arrays.copyOf(seq, seq.length+1); for(int i = seq.length-1; i > start;i--){ seq[i] = seq[i-1]; } seq[start] = num; } } } public static Double GetMedian() { int len = seq.length; if(len %2 ==0){ return (seq[len/2]+seq[len/2-1])/2.0; } return seq[len/2]*1.0; } }
class Solution { private: vector<int> big_part; vector<int> small_part; public: void Insert(int num) { if (small_part.empty()) { small_part.push_back(num); } else { if (small_part.size() == big_part.size()) { if (num <= big_part.front()) { small_part.push_back(num); push_heap(small_part.begin(), small_part.end()); } else { pop_heap(big_part.begin(), big_part.end(), greater<int>()); small_part.push_back(big_part.back()); big_part.back() = num; push_heap(small_part.begin(), small_part.end()); push_heap(big_part.begin(), big_part.end(), greater<int>()); } } else { if (num >= small_part.front()) { big_part.push_back(num); push_heap(big_part.begin(), big_part.end(), greater<int>()); } else { pop_heap(small_part.begin(), small_part.end()); big_part.push_back(small_part.back()); small_part.back() = num; push_heap(small_part.begin(), small_part.end()); push_heap(big_part.begin(), big_part.end(), greater<int>()); } } } } double GetMedian() { if (small_part.size() == big_part.size()) { return static_cast<double>(small_part.front() + big_part.front()) / 2; } else { return small_part.front(); } } };
class Solution { public: void Insert(int num) { data.push_back(num); std::sort(data.begin(), data.end()); } double GetMedian() { unsigned int size = data.size(); if (size & 1) { return data[size >> 1]; } else { int left = data[(size >> 1) - 1]; int right = data[size >> 1]; return (static_cast<double>(left) + right) / 2; } } private: vector<int> data; };
class Solution { priority_queue<int, vector<int>, less<int> > p; priority_queue<int, vector<int>, greater<int> > q; public: void Insert(int num){ if(p.empty() || num <= p.top()) p.push(num); else q.push(num); if(p.size() == q.size() + 2) q.push(p.top()), p.pop(); if(p.size() + 1 == q.size()) p.push(q.top()), q.pop(); } double GetMedian(){ return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top(); } };
/* //弱弱的数据。。。 class Solution { vector<int> v; int n; public: void Insert(int num){ v.push_back(num); n = v.size(); for(int i = n - 1; i > 0 && v[i] < v[i - 1]; --i) swap(v[i], v[i - 1]); } double GetMedian(){ return (v[(n - 1) >> 1] + v[n >> 1]) / 2.0; } }; */
python2.7 时间:30ms 内存:5760k class Solution: def __init__(self): self.arr = [] def Insert(self, num): if len(self.arr)==0: self.arr.append(num) else: i = len(self.arr)-1 while num > self.arr[i]: i -= 1 self.arr.insert(i+1,num) def GetMedian(self, no): # write code here length = len(self.arr) if length %2 ==1 : return self.arr[length//2] else: return (self.arr[length//2] + self.arr[length//2-1])/2
前后段使用的都是小根堆,只是前半段的小根堆加入的是取负号的元素值,从前半段小根堆pop出最小值(负值),取上负号就是最大值了
from heapq import * # 导入小根堆 class Solution: pre = [] # 前半部分 after = [] # 后半部分 def Insert(self, num): pre = self.pre after = self.after # 往后半部分添加元素 # 每次从后半部分pop出一个最小值加入前半部分 # 相当于后半部分长度不变,前半部分长度+1 heappush(pre, -heappushpop(after, num)) # 维持前后段元素个数相差不超过1 if len(after) < len(pre): # 从前半部分pop出一个最小值(这个值是负数,添负号后就是最大值) # 将添负号后的值(前半部分最大值)加入到后半部分 heappush(after, -heappop(pre)) def GetMedian(self): pre = self.pre after = self.after # 后半部分比前半部分多一位,中位数 = 后半部分[0] if len(after) > len(pre): return after[0] else: # 中位数 = (后半部分最小值 + 前半部分最大值 )/ 2 # 因为前部分小根堆里的元素是负值 # pop出最小的负值取负号就能拿到前半部分的最大值 return (after[0] - pre[0]) / 2
import java.util.*; public class Solution { //堆 private PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1); private PriorityQueue<Integer> minHeap = new PriorityQueue<>((o1, o2) -> o1 - o2); public void Insert(Integer num) { if(maxHeap.isEmpty() || num < maxHeap.peek()) maxHeap.add(num); else minHeap.add(num); modifyTwoHeaps(); } public Double GetMedian() { if(maxHeap.size() == minHeap.size()) return ( maxHeap.peek() + minHeap.peek() ) / 2.0; else return maxHeap.size() > minHeap.size() ? (double)maxHeap.peek() : (double)minHeap.peek(); } private void modifyTwoHeaps(){ if(maxHeap.size() == minHeap.size() + 2) minHeap.add(maxHeap.poll()); if(minHeap.size() == maxHeap.size() + 2) maxHeap.add(minHeap.poll()); } }
采用插入排序思想即可解决问题。
import java.util.*; public class Solution { ArrayList list = new ArrayList(); public void Insert(Integer num) { int index = list.size(); for(int i=0;i<index;++i){ if(list.get(i)>num){ index = i; } } list.add(index,num); } public Double GetMedian() { int len = list.size(); if(len==0)return null; int i = len/2; if(len%2==0)return (double )(list.get(i)+list.get(i-1))/2; else return (double)list.get(i); } }
// 从小到大 PriorityQueue<Integer> max = new PriorityQueue<>(); // 从大到小 PriorityQueue<Integer> min = new PriorityQueue<>( (x, y) -> y-x); public void Insert(Integer num) { if(max.size() == min.size()){ min.add(num); max.add(min.poll()); }else{ max.add(num); min.add(max.poll()); } } public Double GetMedian() { return (Double)( max.size() == min.size() ? (max.peek() + min.peek()) / 2.0 : max.peek()); }