这个题还是大顶堆,小顶堆,这个是以1为二叉堆的坐标位置,所以左右子节点坐标分别是21和21+1,一次类推,具体题解我都不注释了这个能看懂
/**
* initialize your data structure here.
*/
var MedianFinder = function() {
this.minHeap = new MinHeap();
this.maxHeap = new MaxHeap();
};
MedianFinder.prototype.addNum = function(num) {
//addNum时,初始直接调用大顶堆的入堆操作,后续的判断大顶堆的堆顶元素和num的关系,如果num小于大顶堆堆顶元素,则入大顶堆,否则入小顶堆,入堆后,会破坏大小顶堆的个数关系,则进行调整,调整的逻辑是哪个堆个数偏大,则删除这个堆的堆顶,并将删除的数入另一个堆,调整一次即可;
if(this.maxHeap.isEmpty()){
this.maxHeap.push(num);
return;
}
if(this.maxHeap.data[1] > num) {
this.maxHeap.push(num);
} else {
this.minHeap.push(num)
}
let minSize = this.minHeap.count;
let maxSize = this.maxHeap.count;
if(minSize > maxSize) {
this.maxHeap.push(this.minHeap.pop());
} else if(maxSize - 1 > minSize) {
this.minHeap.push(this.maxHeap.pop())
}
};
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function () {
let maxSize = this.maxHeap.count;
let minSize = this.minHeap.count;
if (maxSize === minSize) {
return (this.maxHeap.data[1] + this.minHeap.data[1]) / 2;
} else {
return this.maxHeap.data[1];
}
};
/**大顶堆
这个大顶堆堆顶位置用1表示 及其左右节点为2*1
*/
class MaxHeap{
constructor() {
this.data = [0];
this.count = 0;
}
isEmpty(){
return this.count === 0;
}
push(val) {
this.count ++ ;
this.data[this.count] = val;
let i = this.count;
while(parseInt(i/2) > 0 && this.data[i] > this.data[parseInt(i/2)]) {
this.swap(i, parseInt(i/2));
i = parseInt(i/2)
}
}
pop(){
let top = this.data[1];
if(this.count > 1) {
this.data[1] = this.data[this.count];
this.data.splice(this.count,1);
this.count --;
let i = 1;
while(true) {
let maxPos = i;
if(i * 2 <= this.count && this.data[i] < this.data[i*2]) {
maxPos = i* 2
}
if(i * 2 + 1 && this.data[maxPos] < this.data[i*2 + 1]){
maxPos = i*2 + 1
}
if(i === maxPos ) {
break;
}
this.swap(i, maxPos);
i = maxPos;
}
} else {
this.count = 0;
this.data.pop()
}
return top;
}
swap(i,j) {
[this.data[i], this.data[j]] = [this.data[j],this.data[i]]
}
}
/**小顶堆 */
class MinHeap{
constructor() {
this.data = [0];
this.count = 0;
}
push(val) {
this.count ++ ;
this.data[this.count] = val;
let i = this.count;
while(parseInt(i/2) > 0 && this.data[i] < this.data[parseInt(i/2)]) {
this.swap(i, parseInt(i/2));
i = parseInt(i/2)
}
}
pop(){
let top = this.data[1];
if(this.count > 1) {
this.data[1] = this.data[this.count];
this.data.splice(this.count,1);
this.count --;
let i = 1;
while(true) {
let maxPos = i;
if(i * 2 <= this.count && this.data[i] > this.data[i*2]) {
maxPos = i* 2
}
if(i * 2 + 1 && this.data[maxPos] > this.data[i*2 + 1]){
maxPos = i*2 + 1
}
if(i === maxPos ) {
break;
}
this.swap(i, maxPos);
i = maxPos;
}
} else {
this.count = 0;
this.data.pop()
}
return top;
}
swap(i,j) {
[this.data[i], this.data[j]] = [this.data[j],this.data[i]]
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* var obj = new MedianFinder()
* obj.addNum(num)
* var param_2 = obj.findMedian()
*/
以下是错误代码,改造没有成功,本来想着this.count这个属性不用也行,但是改造的老师报错.就先放着了
/**
* initialize your data structure here.
*/
var MedianFinder = function() {
this.minHeap = new MinHeap();
this.maxHeap = new MaxHeap();
};
MedianFinder.prototype.addNum = function(num) {
//addNum时,初始直接调用大顶堆的入堆操作,后续的判断大顶堆的堆顶元素和num的关系,如果num小于大顶堆堆顶元素,则入大顶堆,否则入小顶堆,入堆后,会破坏大小顶堆的个数关系,则进行调整,调整的逻辑是哪个堆个数偏大,则删除这个堆的堆顶,并将删除的数入另一个堆,调整一次即可;
if(this.maxHeap.isEmpty()){
this.maxHeap.push(num);
return;
}
if(this.maxHeap.data[1] > num) {
this.maxHeap.push(num);
} else {
this.minHeap.push(num)
}
let minSize = this.minHeap.count;
let maxSize = this.maxHeap.count;
// let maxSize = this.maxHeap.data.length - 1;
// console.log(minSize, this.minHeap.data.length, this.minHeap.data)
if(minSize > maxSize) {
this.maxHeap.push(this.minHeap.pop());
} else if(maxSize - 1 > minSize) {
this.minHeap.push(this.maxHeap.pop())
}
};
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function () {
// let maxSize = this.maxHeap.data.length - 1;
let maxSize = this.maxHeap.count;
let minSize = this.minHeap.count;
console.log(this.maxHeap.data, maxSize, this.maxHeap.count)
if (maxSize === minSize) {
return (this.maxHeap.data[1] + this.minHeap.data[1]) / 2;
} else {
return this.maxHeap.data[1];
}
};
/**大顶堆
这个大顶堆堆顶位置用1表示 及其左右节点为2*1 2*1+1
*/
class MaxHeap{
constructor() {
this.data = [0];
this.count = 0;
}
isEmpty(){
// return this.data.length - 1 === 0;
return this.count === 0;
}
// push(val) {
// this.count ++ ;
// this.data[this.count] = val;
// let i = this.count;
// // this.data[this.data.length - 1] = val;
// // let i = this.data.length - 1;
// while(parseInt(i/2) > 0 && this.data[i] > this.data[parseInt(i/2)]) {
// this.swap(i, parseInt(i/2));
// i = parseInt(i/2)
// }
// }
push(val) {
this.count++;
this.data[this.count] = val;
let i = this.count;
while (parseInt(i / 2) > 0 && this.data[i] > this.data[parseInt(i / 2)]) {
this.swap(i, parseInt(i / 2));
i = parseInt(i / 2);
}
}
pop() {
let top = this.data[1]
if (this.count > 1) {
this.data[1] = this.data[this.count];
this.data.splice(this.count, 1);
this.count--;
let i = 1;
while (true) {
let maxPos = i;
if (i * 2 <= this.count && this.data[i] < this.data[i * 2]) {
maxPos = i * 2;
}
if (i * 2 + 1 <= this.count && this.data[maxPos] < this.data[i * 2 + 1]) {
maxPos = i * 2 + 1;
}
if (maxPos === i) {
break;
}
this.swap(i, maxPos);
i = maxPos;
}
} else {
this.count = 0;
this.data.splice(1, 1);
}
return top;
}
// pop(){
// let top = this.data[1];
// let count = this.count;
// // let count = this.data.length - 1;
// if(count > 1) {
// this.data[1] = this.data[count];
// this.data.splice(count,1);
// count --;
// let i = 1;
// while(true) {
// let maxPos = i;
// if(i * 2 <= count && this.data[i] < this.data[i*2]) {
// maxPos = i* 2
// }
// if(i * 2 + 1 && this.data[maxPos] < this.data[i*2 + 1]){
// maxPos = i*2 + 1
// }
// if(i === maxPos ) {
// break;
// }
// this.swap(i, maxPos);
// i = maxPos;
// }
// } else {
// count = 0;
// this.data.pop()
// }
// return top;
// }
swap(i,j) {
[this.data[i], this.data[j]] = [this.data[j],this.data[i]]
}
}
/**小顶堆 */
class MinHeap{
constructor() {
this.data = [0];
this.count = 0;
}
push(val) {
this.count ++ ;
this.data[this.count] = val;
let i = this.count;
while(parseInt(i/2) > 0 && this.data[i] < this.data[parseInt(i/2)]) {
this.swap(i, parseInt(i/2));
i = parseInt(i/2)
}
}
pop(){
let top = this.data[1];
if(this.count > 1) {
this.data[1] = this.data[this.count];
this.data.splice(this.count,1);
this.count --;
let i = 1;
while(true) {
let maxPos = i;
if(i * 2 <= this.count && this.data[i] > this.data[i*2]) {
maxPos = i* 2
}
if(i * 2 + 1 && this.data[maxPos] > this.data[i*2 + 1]){
maxPos = i*2 + 1
}
if(i === maxPos ) {
break;
}
this.swap(i, maxPos);
i = maxPos;
}
} else {
this.count = 0;
this.data.pop()
}
return top;
}
swap(i,j) {
[this.data[i], this.data[j]] = [this.data[j],this.data[i]]
}
getSize() {
return this.count;
}
top() {
return this.data[1];
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* var obj = new MedianFinder()
* obj.addNum(num)
* var param_2 = obj.findMedian()
*/