[路飞]_leetcode-面试题 17.20-连续中值

84 阅读1分钟

随机产生数字并传递给一个方法。你能否完成这个方法,在每次产生新值时,寻找当前所有值的中间值(中位数)并保存。 力扣原文

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

  • void addNum(int num) - 从数据流中添加一个整数到数据结构中。
  • double findMedian() - 返回目前所有元素的中位数。

示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3) 
findMedian() -> 2

解题: 双堆记录


 class Heap {
    constructor(cmp,max) {
      const defaultCmp = (a, b) => a > b;
      this.list = [];
      //默认大顶堆
      this.cmp = cmp || defaultCmp;
      this.max=max||null
    }
    size() {
      return this.list.length;
    }
    top() {
      return this.list.length === 0 ? null : this.list[0];
    }
    push(val) {
      this.list.push(val);
      if(this.size()>1){
      this.bubbleUp(this.size() - 1);
      }
      if( this.max!==null&&this.size()> this.max)this.pop()
    }
    pop() {
      if (!this.size()) {
        return null;
      } else if (this.size() === 1) {
        return this.list.pop();
      }
      const top = this.list[0];
      this.list[0] = this.list.pop();
      this.bubbleDown(0);
      return top;
    }
    //向上调整
    bubbleUp(idx) {
      while (idx) {
        let parentIdx = (idx-1)>>1;
        if (this.cmp(this.list[parentIdx],this.list[idx] )) {
          this.swap(idx, parentIdx);
          idx = parentIdx;
        } else {
          break;
        }
      }
    }
    //向下调整
    bubbleDown() {
      let cur = 0,leftIdx=1,rightIdx=2,size=this.size()
      while(
       ( leftIdx<size&&this.cmp(this.list[cur],this.list[leftIdx]))||
       ( rightIdx<size&&this.cmp(this.list[cur],this.list[rightIdx]))
      ){
        if(rightIdx<size&&this.cmp(this.list[leftIdx],this.list[rightIdx])){
          this.swap(rightIdx,cur)
          cur=rightIdx
         
        }else{
          this.swap(leftIdx,cur)
          cur=leftIdx
        }
        leftIdx=cur*2+1,rightIdx=cur*2+2
      }
    }
    // 交换
    swap(i, j) {
      [this.list[i], this.list[j]] = [this.list[j], this.list[i]];
    }
  }
  function comp(a,b){
    
    return a<b
}
var MedianFinder = function() {
   
    this.maxHeap=new Heap((a,b)=>a<b)
    this.minHeap=new Heap((a,b)=>a>b)
};

MedianFinder.prototype.addNum = function(num) {
   if(this.maxHeap.size()===0||num<=this.maxHeap.top()){
       this.maxHeap.push(num)
       if(this.maxHeap.size()>this.minHeap.size()+1){
        this.minHeap.push(this.maxHeap.pop())
    }
   }else{
       this.minHeap.push(num)
       if(this.minHeap.size()>this.maxHeap.size()){
            this.maxHeap.push(this.minHeap.pop())
    }
   }
};
MedianFinder.prototype.findMedian = function() {
    let len=this.maxHeap.size()+this.minHeap.size()
    if(len%2===1){
        return this.maxHeap.top()
    }else{
        return (this.minHeap.top()+this.maxHeap.top())/2
    }
};