一、题目内容

image.png

二、题解

解法1:

思路

双堆,一个大堆一个小堆
大堆存储较小的数据,堆顶为堆的最大值
小堆存储较大的数据,堆顶为堆的最小值

使用优先队列 PriorityQueue

代码

  1. public class MedianFinder {
  2. Queue<Integer> min_heap, max_heap;
  3. /**
  4. * min_heap max_heap
  5. * max->min min->max
  6. * initialize your data structure here.
  7. */
  8. public MedianFinder() {
  9. min_heap = new PriorityQueue<>(new Comparator<Integer>() {
  10. @Override
  11. public int compare(Integer o1, Integer o2) {
  12. //升序
  13. return o1 - o2;
  14. }
  15. }); // 小顶堆,保存较大的一半
  16. max_heap = new PriorityQueue<>(new Comparator<Integer>() {
  17. @Override
  18. public int compare(Integer o1, Integer o2) {
  19. //降序
  20. return o2 - o1;
  21. }
  22. }); // 大顶堆,保存较小的一半
  23. }
  24. /**
  25. * 如果两个数组相等:大顶堆+1
  26. * 不相等:小顶堆+1
  27. *
  28. * @param num
  29. */
  30. public void addNum(int num) {
  31. if (min_heap.size() != max_heap.size()) {
  32. min_heap.add(num);
  33. max_heap.add(min_heap.poll());
  34. } else {
  35. max_heap.add(num);
  36. min_heap.add(max_heap.poll());
  37. }
  38. }
  39. public double findMedian() {
  40. return min_heap.size() != max_heap.size() ? min_heap.peek() : (min_heap.peek() + max_heap.peek()) / 2d;
  41. }
  42. }

解法2:

思路

类似插入排序,通过二分查找,找到小的大于num的index;如果均小于则追加末尾

代码

  1. class MedianFinder {
  2. private ArrayList<Integer> list;
  3. /** initialize your data structure here. */
  4. public MedianFinder() {
  5. list = new ArrayList<Integer>();
  6. }
  7. /**
  8. * 插入
  9. *
  10. * @param num
  11. */
  12. public void addNum(int num) {
  13. if (list.isEmpty()) {
  14. list.add(num);
  15. return;
  16. }
  17. int maxIndex = list.size() - 1;
  18. int pos = findPos(num);
  19. //如果返回的可插入位置大于最大index,则直接追加,否则插入pos位置,pos后数据顺序移动一位
  20. if (pos > maxIndex) {
  21. list.add(num);
  22. } else {
  23. list.add(findPos(num), num);
  24. }
  25. }
  26. //找到第一个大于nums的index;如果均小于num,则返回 maxIndex+1
  27. public int findPos(int num) {
  28. int left = 0;
  29. int right = list.size() - 1;
  30. while (left < right) {
  31. int mid = (left + right) / 2;
  32. if (list.get(mid) > num) {
  33. right = mid;
  34. } else {
  35. left = mid + 1;
  36. }
  37. }
  38. if (list.get(right) > num) {
  39. return right;
  40. } else {
  41. return right + 1;
  42. }
  43. }
  44. // 奇数 len/2
  45. // 偶数 (len/2-1 + len/2 ) /2d
  46. public double findMedian() {
  47. int len = list.size();
  48. if (len % 2 == 0) {
  49. return (list.get(len / 2 - 1) + list.get(len / 2)) / 2d;
  50. } else {
  51. return list.get(len / 2);
  52. }
  53. }
  54. }