![问题](https://img-blog.csdn.net/20180420134958789?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTIwMTc3ODM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
一、解题思路
![解法](https://img-blog.csdn.net/20180420135009410?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTIwMTc3ODM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
二、具体代码
import java.util.*;
public class FindMidNum{
private MyHeap<Integer>minHeap;
private MyHeap<Integer>maxHeap;
public FindMidNum(){
this.maxHeap=new MyHeap<Integer>(new maxHeapComparator());
this.minHeap=new MyHeap<Integer>(new minHeapComparator());
}
public void addNumber(Integer num){
if(this.maxHeap.isEmpty()){
this.maxHeap.add(num);
return;
}
if(this.maxHeap.getHead()>=num){
this.maxHeap.add(num);
}else{
if(this.minHeap.isEmpty()){
this.minHeap.add(num);
return;
}
if(this.minHeap.getHead()>num){
this.maxHeap.add(num);
}else{
this.minHeap.add(num);
}
}
this.modifyTwoHeapsSize();
}
public Integer getMedian(){
long maxHeapSize=this.maxHeap.getSize();
long minHeapSize=this.minHeap.getSize();
if(maxHeapSize+minHeapSize==0){
return null;
}
Integer maxHeapHead=this.maxHeap.getHead();
Integer minHeapHead=this.minHeap.getHead();
if(((maxHeapSize+minHeapSize)&1)==0){
return (maxHeapHead+minHeapHead)/2;
}else if(maxHeapSize>minHeapSize){
return maxHeapHead;
}else{
return minHeapHead;
}
}
private void modifyTwoHeapsSize(){
if(this.maxHeap.getSize()==this.minHeap.getSize()+2){
this.minHeap.add(this.maxHeap.popHead());
}
if(this.minHeap.getSize()==this.maxHeap.getSize()+2){
this.maxHeap.add(this.minHeap.popHead());
}
}
public static int[] getRandomArray(int maxLen, int maxValue) {
int[] res = new int[(int) (Math.random() * maxLen) + 1];
for (int i = 0; i != res.length; i++) {
res[i] = (int) (Math.random() * maxValue);
}
return res;
}
public static int getMedianOfArray(int[] arr) {
int[] newArr = Arrays.copyOf(arr, arr.length);
Arrays.sort(newArr);
int mid = (newArr.length - 1) / 2;
if ((newArr.length & 1) == 0) {
return (newArr[mid] + newArr[mid + 1]) / 2;
} else {
return newArr[mid];
}
}
public static void printArray(int[] arr) {
for (int i = 0; i != arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[]args){
System.out.println("Hello");
boolean err = false;
int testTimes = 20;
for (int i = 0; i != testTimes; i++) {
int len = 30;
int maxValue = 1000;
int[] arr = getRandomArray(len, maxValue);
FindMidNum findMid=new FindMidNum();
for (int j = 0; j != arr.length; j++) {
findMid.addNumber(arr[j]);
}
if (findMid.getMedian() != getMedianOfArray(arr)) {
err = true;
printArray(arr);
break;
}
}
}
}
class maxHeapComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1,Integer o2){
if(o2>o1){
return 1;
}else{
return -1;
}
}
}
class minHeapComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1,Integer o2){
if(o2<o1){
return 1;
}else{
return -1;
}
}
}
class MyHeap<K> {
private Node<K> head;
private Node<K> last;
private long size;
private Comparator<K> comp;
public MyHeap(Comparator<K> compare) {
head = null;
last = null;
size = 0;
comp = compare;
}
public K getHead() {
return head == null ? null : head.value;
}
public long getSize() {
return size;
}
public boolean isEmpty() {
return size == 0 ? true : false;
}
public void add(K value) {
Node<K> newNode = new Node<K>(value);
if (size == 0) {
head = newNode;
last = newNode;
size++;
return;
}
Node<K> node = last;
Node<K> parent = node.parent;
while (parent != null && node != parent.left) {
node = parent;
parent = node.parent;
}
Node<K> nodeToAdd = null;
if (parent == null) {
nodeToAdd = mostLeft(head);
nodeToAdd.left = newNode;
newNode.parent = nodeToAdd;
} else if (parent.right == null) {
parent.right = newNode;
newNode.parent = parent;
} else {
nodeToAdd = mostLeft(parent.right);
nodeToAdd.left = newNode;
newNode.parent = nodeToAdd;
}
last = newNode;
heapInsertModify();
size++;
}
public K popHead() {
if (size == 0) {
return null;
}
Node<K> res = head;
if (size == 1) {
head = null;
last = null;
size--;
return res.value;
}
Node<K> oldLast = popLastAndSetPreviousLast();
if (size == 1) {
head = oldLast;
last = oldLast;
return res.value;
}
Node<K> headLeft = res.left;
Node<K> headRight = res.right;
oldLast.left = headLeft;
if (headLeft != null) {
headLeft.parent = oldLast;
}
oldLast.right = headRight;
if (headRight != null) {
headRight.parent = oldLast;
}
res.left = null;
res.right = null;
head = oldLast;
heapify(oldLast);
return res.value;
}
private Node<K> mostLeft(Node<K> node) {
while (node.left != null) {
node = node.left;
}
return node;
}
private Node<K> mostRight(Node<K> node) {
while (node.right != null) {
node = node.right;
}
return node;
}
private void heapInsertModify() {
Node<K> node = last;
Node<K> parent = node.parent;
if (parent != null && comp.compare(node.value, parent.value) < 0) {
last = parent;
}
while (parent != null && comp.compare(node.value, parent.value) < 0) {
swapClosedTwoNodes(node, parent);
parent = node.parent;
}
if (head.parent != null) {
head = head.parent;
}
}
private void heapify(Node<K> node) {
Node<K> left = node.left;
Node<K> right = node.right;
Node<K> most = node;
while (left != null) {
if (left != null && comp.compare(left.value, most.value) < 0) {
most = left;
}
if (right != null && comp.compare(right.value, most.value) < 0) {
most = right;
}
if (most != node) {
swapClosedTwoNodes(most, node);
} else {
break;
}
left = node.left;
right = node.right;
most = node;
}
if (node.parent == last) {
last = node;
}
while (node.parent != null) {
node = node.parent;
}
head = node;
}
private void swapClosedTwoNodes(Node<K> node, Node<K> parent) {
if (node == null || parent == null) {
return;
}
Node<K> parentParent = parent.parent;
Node<K> parentLeft = parent.left;
Node<K> parentRight = parent.right;
Node<K> nodeLeft = node.left;
Node<K> nodeRight = node.right;
node.parent = parentParent;
if (parentParent != null) {
if (parent == parentParent.left) {
parentParent.left = node;
} else {
parentParent.right = node;
}
}
parent.parent = node;
if (nodeLeft != null) {
nodeLeft.parent = parent;
}
if (nodeRight != null) {
nodeRight.parent = parent;
}
if (node == parent.left) {
node.left = parent;
node.right = parentRight;
if (parentRight != null) {
parentRight.parent = node;
}
} else {
node.left = parentLeft;
node.right = parent;
if (parentLeft != null) {
parentLeft.parent = node;
}
}
parent.left = nodeLeft;
parent.right = nodeRight;
}
private Node<K> popLastAndSetPreviousLast() {
Node<K> node = last;
Node<K> parent = node.parent;
while (parent != null && node != parent.right) {
node = parent;
parent = node.parent;
}
if (parent == null) {
node = last;
parent = node.parent;
node.parent = null;
if (node == parent.left) {
parent.left = null;
} else {
parent.right = null;
}
last = mostRight(head);
} else {
Node<K> newLast = mostRight(parent.left);
node = last;
parent = node.parent;
node.parent = null;
if (node == parent.left) {
parent.left = null;
} else {
parent.right = null;
}
last = newLast;
}
size--;
return node;
}
public void changeHead(K value) {
if (this.head != null) {
Node<K> newNode = new Node<K>(value);
Node<K> headLeft = this.head.left;
Node<K> headRight = this.head.right;
if (headLeft != null) {
headLeft.parent = newNode;
newNode.left = headLeft;
}
if (headRight != null) {
headRight.parent = newNode;
newNode.right = headRight;
}
this.head.left = null;
this.head.right = null;
this.head = newNode;
this.heapify(this.head);
}
}
public void printHeapByLevel() {
if (this.size == 0) {
System.out.println("Heap Empty!");
return;
}
System.out.println("Head: " + this.head.value);
System.out.println("Last: " + this.last.value);
System.out.println("Size: " + this.size);
printBinaryTreeByDepth(this.head);
}
private void printBinaryTreeByDepth(Node<K> head) {
Queue<Node<K>> nodeQueue = new LinkedList<Node<K>>();
Node<K> levelLastNode = head;
Node<K> nextLevelLastNode = null;
int levelNum = 0;
nodeQueue.add(head);
System.out.print("Level 0 nodes: ");
while (!nodeQueue.isEmpty()) {
Node<K> current = nodeQueue.poll();
System.out.print(current.value + " ");
if (current.left != null) {
nextLevelLastNode = current.left;
nodeQueue.add(current.left);
}
if (current.right != null) {
nextLevelLastNode = current.right;
nodeQueue.add(current.right);
}
if (current == levelLastNode) {
levelLastNode = nextLevelLastNode;
nextLevelLastNode = null;
System.out.println();
if (levelLastNode != null) {
System.out.print("Level " + (++levelNum) + " nodes: ");
}
}
}
}
}
class MyComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
if (o2 > o1) {
return 1;
} else {
return -1;
}
}
}
class Node<K> {
public K value;
public Node<K> left;
public Node<K> right;
public Node<K> parent;
public Node(K data) {
value = data;
}
}