设计一个找到数据流中第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