js(67)~面试题 17.20. 连续中值

118 阅读3分钟

力扣本题传送门

这个题还是大顶堆,小顶堆,这个是以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()
 */