設計一個找到數據流中第K大元素的類(class)。注意是排序後的第K大元素,不是第K個不一樣的元素。javascript
你的 KthLargest 類須要一個同時接收整數 k 和整數數組nums 的構造器,它包含數據流中的初始元素。每次調用 KthLargest.add,返回當前數據流中第K大的元素。java
優勢:直觀api
優勢:時間複雜度較低
缺點:若是語言自己沒有實現優先隊列,則須要本身實現,代碼較複雜。數組
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