一、题目

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

  • void addNum(int num) - 从数据流中添加一个整数到数据结构中。
  • double findMedian() - 返回目前所有元素的中位数。

点击查看原题
难度级别: 困难

二、思路

1)数组存数据+二分查找+线性插入

用一个ArrayList存储数据,保证其有序,每次插入进行二分查找位置,再插入进去
返回结果时,判断容量是否奇偶

2)大小根堆

用两个根堆,大根堆存储小值部分,小根堆存储大值部门,每次插入进行判断num该进入哪个堆,并做好两个堆数据容量的平衡
返回结果只需要判断两个根堆大小,来进行返回

三、代码

1)数组存数据+二分查找+线性插入

  1. class MedianFinder {
  2. private List<Integer> nums;
  3. /** initialize your data structure here. */
  4. public MedianFinder() {
  5. nums = new ArrayList();
  6. }
  7. public void addNum(int num) {
  8. int loc = searchByBinary(num);
  9. if (loc == nums.size()) {
  10. nums.add(num);
  11. } else {
  12. nums.add(loc, num);
  13. }
  14. }
  15. private int searchByBinary(int num) {
  16. int s = 0, e = nums.size();
  17. while (s < e) {
  18. int mid = (s + e)/2;
  19. if (nums.get(mid) == num) {
  20. return mid;
  21. } else if (nums.get(mid) > num) {
  22. e = mid;
  23. } else {
  24. s = mid + 1;
  25. }
  26. }
  27. return s;
  28. }
  29. public double findMedian() {
  30. if ((nums.size() & 1) == 1) {
  31. return (double)nums.get(nums.size()/2);
  32. }
  33. return (double)((double)nums.get(nums.size()/2 - 1) + (double)nums.get(nums.size()/2 ))/2;
  34. }
  35. }

查找和插入时间复杂度O(logn+n),返回中位数时间复杂度O(1),空间复杂度为O(n)

1)数组存数据+二分查找+线性插入

  1. class MedianFinder {
  2. private PriorityQueue<Integer> minH = new PriorityQueue(); //存高部分
  3. private PriorityQueue<Integer> maxH = new PriorityQueue<Integer>((i1, i2) -> (i2 - i1)); // 存低位
  4. /** initialize your data structure here. */
  5. public MedianFinder() {
  6. }
  7. public void addNum(int num) {
  8. if (maxH.size() == 0) {
  9. maxH.add(num);
  10. } else if (maxH.peek() <= num) {
  11. minH.add(num);
  12. if (minH.size() > maxH.size() + 1) {
  13. maxH.add(minH.poll());
  14. }
  15. } else {
  16. maxH.add(num);
  17. if (maxH.size() >= minH.size() + 1) {
  18. minH.add(maxH.poll());
  19. }
  20. }
  21. }
  22. public double findMedian() {
  23. if (maxH.size() == minH.size()) {
  24. return ((double)maxH.peek() + (double)minH.peek())/2d;
  25. }
  26. if (maxH.size() > minH.size()) {
  27. return (double)maxH.peek();
  28. }
  29. return (double)minH.peek();
  30. }
  31. }

插入时间复杂度O(logn),返回中位数时间复杂度O(1),空间复杂度为O(n)