设计一个找到数据流中第 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
一、常规解法:
需要找到数据流中第K大的元素,那么就首先需要排序,实现 KthLargest 类的构造,进行排序
var KthLargest = function(k, nums) {
for (let j = 0; j < nums.length - 1; j++) {
for (let i = 0; i < nums.length - 1; i++) {
let current = nums[i]
let next = nums[i + 1]
if (current > next) {
let temp = nums[i]
nums[i] = nums[i + 1]
nums[i + 1] = temp
}
}
}
this.k = k
this.nums = nums
};
对象使用 add() 方法后,将添加数据 push 到 数据流最后,再次进行插入排序,仅仅针对最后一个元素插入即可,实现 add 方法:
KthLargest.prototype.add = function(val) {
this.nums.push(val)
let insertIndex = this.nums.length - 2
while (insertIndex >= 0 && this.nums[insertIndex] > val) {
this.nums[insertIndex + 1] = this.nums[insertIndex]
insertIndex--
}
this.nums[insertIndex + 1] = val
return this.nums[this.nums.length - this.k]
};
插入排序算法不再赘述,可以参考之前的文章: 插入排序
由于代码是从小到大排序的,那么最大的数据在 数据长度 - 插入下标,最终返回。
完整代码:
/**
* @param {number} k
* @param {number[]} nums
*/
var KthLargest = function(k, nums) {
for (let j = 0; j < nums.length - 1; j++) {
for (let i = 0; i < nums.length - 1; i++) {
let current = nums[i]
let next = nums[i + 1]
if (current > next) {
let temp = nums[i]
nums[i] = nums[i + 1]
nums[i + 1] = temp
}
}
}
this.k = k
this.nums = nums
};
/**
* @param {number} val
* @return {number}
*/
KthLargest.prototype.add = function(val) {
this.nums.push(val)
let insertIndex = this.nums.length - 2
while (insertIndex >= 0 && this.nums[insertIndex] > val) {
this.nums[insertIndex + 1] = this.nums[insertIndex]
insertIndex--
}
this.nums[insertIndex + 1] = val
return this.nums[this.nums.length - this.k]
};
结果:
二、JS 快捷解法:
由于 JS API 的特点,可以在思路保持不变的情况下使用 JS 独有的 API,达到快速方便解题的目的。
/**
* @param {number} k
* @param {number[]} nums
*/
var KthLargest = function(k, nums) {
this.nums = nums.sort((a, b) => b - a)
this.k = k
};
/**
* @param {number} val
* @return {number}
*/
KthLargest.prototype.add = function(val) {
this.nums.push(val)
return this.nums.sort((a, b) => b - a)[this.k - 1]
};
结果:
比较两种解法:JS API 虽然代码量非常少,但是内存占用较大,且执行用时是常规解法的将近9倍,如果在实际问题中,需要考虑取舍!