维护实时中位数和秩
1.实时中位数 leecode 295
/* * solution : * 1.利用PriorityQueue新建两个堆,一个大根堆maxHeap(需要自己实现比较器),一个小根堆minHeap * 2.插入元素时,让大根堆的堆顶元素始终小于等于中位数,小根堆的堆顶元素始终大于中位数 * 3.所以元素个数为奇数个时,大根堆比小根堆多一个元素,且中位数为大根堆堆顶元素;元素个数为偶数时,两堆一样高,中位数为两堆顶元素的平均值 * 4.主要是插入元素时,要根据两堆的size来与堆顶元素进行比较,决定插入哪个堆 */ public class S295 { private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new MaxComparator()); private PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); // Adds a number into the data structure. public void addNum(int num) { if (maxHeap.size() > minHeap.size()) { if (num < maxHeap.peek()) { minHeap.offer(maxHeap.poll()); maxHeap.offer(num); } else { minHeap.offer(num); } } else { if (maxHeap.size() == 0) { maxHeap.offer(num); } else { if (num > minHeap.peek()) { maxHeap.offer(minHeap.poll()); minHeap.offer(num); } else { maxHeap.offer(num); } } } } // Returns the median of current data stream public double findMedian() { if (maxHeap.size() == 0) return -1; if (maxHeap.size() == minHeap.size()) { return (double)(maxHeap.peek() + minHeap.peek()) / 2; } else { return maxHeap.peek(); } } } class MaxComparator implements Comparator<Integer> { @Override public int compare(Integer a, Integer b) { if (a > b) { return -1; } else if (a < b) { return 1; } else { return 0; } } }
2.实时秩 某个数的秩是当前数组中小于等于这个数的数的个数 程序员面试金典 P267 11-8
/*
* solution:
* 维护实时秩其实就是使数组始终有序,很容易想到了二叉查找树,不过要给每个节点实时记录左子节点个数leftSize。
* 我们从二叉查找树的根节点开始查找,会出现三种情况
* 1. 当前节点值等于当前值,则当前值的秩则是当前节点的leftSize
* 2. 当前节点值大于当前值,则要往当前节点的左子节点继续查找
* 3. 当前节点值小于当前值,则当前值的秩首先得加上当前节点值的leftSize + 1(1代表当前节点本身),再往右继续查找
*/
import java.util.*; public class Rank { RankNode root = null; public int[] getRankOfNumber(int[] A, int n) { // write code here int[] rank = new int[n]; for (int i = 0; i < n; i++) { track(A[i]); rank[i] = root.getRank(A[i]); } return rank; } public void track(int val) { if (root == null) root = new RankNode(val); else root.insert(val); } } class RankNode { RankNode left = null, right = null; int val = 0; int leftSize = 0; public RankNode(int val) { this.val = val; } public void insert(int val) { if (val <= this.val) { if (this.left != null) this.left.insert(val); else this.left = new RankNode(val); this.leftSize++; } else { if (this.right != null) this.right.insert(val); else this.right = new RankNode(val); } } public int getRank(int val) { if (val == this.val) return this.leftSize; if (val > this.val) { if(this.right == null) return -1; return this.leftSize + 1 + this.right.getRank(val); } if (this.left == null) return -1; return this.left.getRank(val); } }