leetcode703 javascript

題目

設計一個找到數據流中第K大元素的類(class)。注意是排序後的第K大元素,不是第K個不一樣的元素。javascript

你的 KthLargest 類須要一個同時接收整數 k 和整數數組nums 的構造器,它包含數據流中的初始元素。每次調用 KthLargest.add,返回當前數據流中第K大的元素。java

解法

維護K個有序數組

優勢:直觀api

維護長度爲K的最小堆

優勢:時間複雜度較低
缺點:若是語言自己沒有實現優先隊列,則須要本身實現,代碼較複雜。數組

待優化的代碼

var KthLargest = function(k, nums) {
  this.k = k
  this.minHeap = new Array(k)

  this.updateHeap = () => {
    let minNum = this.minHeap[0]
    let minIndex = 0
    for(let i = 1; i < this.minHeap.length; i ++) {
      if(minNum >= this.minHeap[i]) {
        minNum = this.minHeap[i]
        minIndex = i
      }
    }
    this.minHeap.push(minNum)
    this.minHeap.splice(minIndex, 1)
  }
  if(nums.length >= k) {
    this.minHeap = nums.filter((value, index) => index < k).map(value => value)
    this.updateHeap()
    // console.log(this.minHeap)
    for(let i = k; i < nums.length; i ++) {
      if(this.minHeap[this.minHeap.length - 1] <= nums[i]) {
        this.minHeap[this.minHeap.length - 1] = nums[i]
      }
      this.updateHeap()
    }
  } else {
    this.minHeap = nums.map((value, index) => {
      return nums[index]
    })
    this.updateHeap()
  }
  console.log(this.minHeap)
};


/** * @param {number} val * @return {number} */
KthLargest.prototype.add = function(val) {
  if(this.minHeap.length < this.k) {
    this.minHeap.push(val)
    this.updateHeap()
  } else if(this.minHeap[this.minHeap.length - 1] < val) {
    this.minHeap[this.minHeap.length - 1] = val
    this.updateHeap()
  }
  console.log(this.minHeap[this.minHeap.length - 1], 'add', val, 
  // this.minHeap
  )
  return this.minHeap[this.minHeap.length - 1]
};
複製代碼


更新一波

今天不作新題,打算把昨天的解題優化一下,首先能想到的就是更新堆的循環改爲while循環,兩個指針同時從左右開始循環,這樣平均狀況下直接就能夠減小n/2的時間複雜度。
因而乎,開始改進,放上去代碼,結果大跌眼鏡,結果並無快不少,好像差很少?!學習

let left_i = 0
    let right_i = this.minHeap.length
    while (left_i <= right_i) {
      if(minNum >= this.minHeap[left_i]) {
        minNum = this.minHeap[left_i]
        minIndex = left_i
      }
      if(minNum >= this.minHeap[right_i]) {
        minNum = this.minHeap[right_i]
        minIndex = right_i
      }
      left_i ++
      right_i --
    }
複製代碼

冥思苦想,耐不住,直接去看執行最快的範例代碼,人家是這麼寫的優化

var heapify = function (arr, i) {
    let len = arr.length,
        left = 2 * i,
        right = 2 * i + 1,
        minimum = i;

    if (left < len && arr[left] < arr[minimum]) minimum = left;
    if (right < len && arr[right] < arr[minimum]) minimum = right;

    if (minimum !== i) {
        const tmp = arr[i];
        arr[i] = arr[minimum];
        arr[minimum] = tmp;
        heapify(arr, minimum);
    }
}

var buildMinHeap = function (arr) {
    const len = arr.length;
    for (let i = Math.floor(len / 2); i >= 0; i--) {
        heapify(arr, i);
    }
}


/** * @param {number} k * @param {number[]} nums */
var KthLargest = function (k, nums) {
    let i = 0, len = nums.length;
    this.k = k;
    this.nums = [];
    for (i = 0; i < k && i < len; i++) {
        this.nums[i] = nums[i];
    }
    buildMinHeap(this.nums);
    for (; i < len; i++) {
        const num = nums[i];
        if (this.nums[0] < num) {
            this.nums[0] = num;
            heapify(this.nums, 0);
        }
    }
};

/** * @param {number} val * @return {number} */
KthLargest.prototype.add = function (val) {
    const k = this.k;
    if (this.nums.length === k) {
        if (this.nums[0] < val) {
            this.nums[0] = val;
            heapify(this.nums, 0);
        }
    } else {
        this.nums.push(val);
        buildMinHeap(this.nums);
    }
    return this.nums[0];
};
複製代碼

寫了個更新最小堆和搭建最小堆的方法,代碼很是簡潔,其中一句代碼看着很是舒服for (i = 0; i < k && i < len; i++) {這個for循環中間的條件,原來條件還能夠這麼玩兒,漲姿式了。ui


加油,天天學習一點點。this

相關文章
相關標籤/搜索