题目描述
题目取自 LeetCode 703. 数据流中的第 K 大元素
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。
请实现 KthLargest 类:
KthLargest(int k, int[] nums)使用整数k和整数流nums初始化对象。int add(int val)将val插入数据流nums后,返回当前数据流中第k大的元素。
示例:
输入:
["KthLargest", "add", "add", "add", "add", "add"]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
输出:
[null, 4, 5, 5, 8, 8]
解释:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3); // return 4
kthLargest.add(5); // return 5
kthLargest.add(10); // return 5
kthLargest.add(9); // return 8
kthLargest.add(4); // return 8
思路
解题思路可以分为以下几个步骤:
- 维护一个
size = k的数组/堆Q - 当添加一个元素
a,和Q中的最小值min进行比较:a <= min,则元素a无需加入Q中- 否则,将元素
a加入Q中并重新调整顺序和大小,使得Q始终保存前 k 大个元素
这里,维护前 K 大元素的解法有很多,从数据结构来讲,维护一个小顶堆是更优的解法,但是我们也可以简单通过一个数组调整。
题解
/**
* @param {number} k
* @param {number[]} nums
*/
var KthLargest = function (k, nums) {
this.k = k;
// 从大到小排序,并取前 k 个元素
this.nums = nums.sort((a, b) => b - a).slice(0, k);
};
/**
* @param {number} val
* @return {number}
*/
KthLargest.prototype.add = function (val) {
// 当元素不足 k,或者新元素大于最小值时,找到对应顺序插入
if (this.nums.length < this.k || val > this.nums[this.nums.length - 1]) {
let i = 0;
while (this.nums[i] > val) i++;
this.nums.splice(i, 0, val);
if (this.nums.length > this.k) {
this.nums.pop();
}
}
return this.nums[this.nums.length - 1];
};
/**
* Your KthLargest object will be instantiated and called as such:
* var obj = new KthLargest(k, nums)
* var param_1 = obj.add(val)
*/
总结
课后题:JavaScript 实现一个小顶堆 PriorityQueue 来解决本题。
var KthLargest = function (k, nums) {
this.k = k;
this.q = new PriorityQueue(nums);
};
/**
* @param {number} val
* @return {number}
*/
KthLargest.prototype.add = function (val) {
if (this.q.size() < this.k) {
this.q.offer(val);
} else if (this.q.peek() < val) {
this.q.poll();
this.q.offer(val);
}
return this.q.peek();
};