对顶堆,顾名思义就是两个相对的堆。O(logn)
0即上方是一个维护最小值的小根堆smheap,下方则维护最大值的大根堆bgheap。
利用这样的性质,我们就可以求中位数、动态维护K大值。优先队列是用堆来实现的。
思路:(我们必须保证小根堆里面的所有值是大于大根堆里面所有值的)
1. 如果要插入的值x>smheap.top(),那么就往smheap里面放。
2. 如果要插入的值x<=smheap.top(),那么就往bgheap里面放。
3. 如果smheap.size() == bgheap.size() + 2,那么就把smheap的堆顶元素移入bgheap
4. 如果bgheap.size() == smheap.size() + 2,那么就把bgheap的堆顶元素移入smheap
PriorityQueue<Integer> pq = new PriorityQueue<>(); //小根堆 PriorityQueue<Integer> pq1 = new PriorityQueue<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { if (o1 == o2) { return 0; } else { if (o1 > o2) { return -1; } else { return 1; } } } });//大根堆 public double findMedianSortedArrays(int[] nums1, int[] nums2) { for (int i = 0; i < nums1.length; i++) { insert(nums1[i]); } for (int i = 0; i < nums2.length; i++) { insert(nums2[i]); } if(pq.size() == pq1.size() + 1) return pq.peek(); else if(pq1.size() == pq.size() + 1) return pq1.peek(); return (pq.peek() + pq1.peek()) / 2.0; } private void insert(int x) { if (pq.isEmpty() || x > pq.peek()) { pq.add(x); } else { pq1.add(x); } if(pq.size() == pq1.size() + 2){ pq1.add(pq.poll()); } else if(pq1.size() == pq.size() + 2){ pq.add(pq1.poll()); } }
一、 nth_element(first,nth,last) stl中的一个函数 时间复杂度是O(n)
主要实现:利用快排的思想,在[L,R]上,通过线性的扫描交换,使[L,mid)的元素都比mid小,(mid,R]的元素都比mid大,此时mid上的元素就是第mid小的元素,然后判断k在mid的哪边,在进行递归处理。
实际上也就是每次只处理一半的范围。
二、维护一个k大小的最小堆,这种方法可以用于数据量存放不下,极大减小了空间复杂度。
三、利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)