给定整数数组
nums和整数k,请返回数组中第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。
思路:排序
最容易想到的是:将数组从大到小排序,然后取第k个值。可以直接使用js提供的sort方法
var findKthLargest = function(nums, k) {
return nums.sort((a, b) => (b - a))[k - 1]
};
sort方法内部是用插入排序或者快排,前者的时间复杂度为O(n^2)后缀为O(nlogn)。
思路:堆排序
利用最大堆,保存数组的中的值,然后弹出k-1次,堆顶即为第k大的值
最大堆的实现可以看专栏文章的前几篇。
// 最大堆实现
class MaxBinaryHeap {
constructor(data, k) {
this.s = []
this.len = 0
this.heapify(data)
}
heapify(data) {
for (let i = 0; i < data.length; i++) {
this.push(data[i])
}
}
push(el) {
this.s[this.len] = el
++this.len
if (this.len > 1) {
this.swim(this.len - 1)
}
}
pop() {
if (this.len === 0) {
return null
}
const top = this.s[0]
if (this.len > 1) {
this.s[0] = this.s[this.len - 1]
this.sink(0)
}
this.len--
return top
}
peek() {
if (this.len === 0) {
return null
} else {
return this.s[0]
}
}
sink(idx) {
const lastIdx = this.len - 1
while (idx <= lastIdx) {
const rightIdx = (idx + 1) * 2
const leftIdx = rightIdx - 1
if (leftIdx <= lastIdx) {
let larger = leftIdx
if (rightIdx <= lastIdx && this.compare(rightIdx, larger) > 0) {
larger = rightIdx
}
if (this.compare(idx, larger) < 0) {
this.swap(idx, larger)
idx = larger
} else {
break
}
} else {
break
}
}
}
swim(idx) {
while (idx >= 0) {
let parent = (idx - 1) >> 1
if (parent >= 0 && this.compare(parent, idx) < 0) {
this.swap(parent, idx)
idx = parent
} else {
break
}
}
}
swap(a, b) {
let temp = this.s[a]
this.s[a] = this.s[b]
this.s[b] = temp
}
compare(a, b) {
return this.s[a] - this.s[b]
}
}
var findKthLargest = function(nums, k) {
const mbh = new MaxBinaryHeap(nums, k)
// pop k - 1次 堆顶即为第k大值
while(--k) {
mbh.pop()
}
return mbh.peek()
};