题目详情:最小的 k 个数
1. 思路
一种思路是利用快速排序,然后取前 k 个数。
另一种思路是构建一个大顶堆。数组中的数字依次进入大顶堆,当堆的长度小于 的时候,则加入堆尾,然后自底向上进行堆调整;当堆的长度大于等于 的时候,就比较堆顶元素和进入的数字,如果进入的数字大,则直接丢弃;反之,则将堆定元素替换成进入的数字,然后自顶向下进行堆调整。
2. 代码(JavaScript 版)
/**
* @param {number[]} arr
* @param {number} k
* @return {number[]}
*/
const swip = (arr, i, j) => {
const temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
const heapify = (result, num, k) => {
if (result.length < k) {
result.push(num)
let index = result.length - 1
// 自底向上调整堆
while (result[index] > result[Math.floor(index / 2)]) {
const nextIndex = Math.floor(index / 2)
swip(result, index, nextIndex)
index = nextIndex
}
} else {
if (num < result[1]) {
result[1] = num
}
let index = 1
// 自上而下调整堆
while (index < result.length) {
const leftIndex = index * 2
const rightIndex = leftIndex + 1
const left = result[leftIndex]
const right = result[rightIndex]
let nextIndex = left > right ? leftIndex : rightIndex
if (num < Math.max(left, right)) {
swip(result, index, nextIndex)
index = nextIndex
} else {
break
}
}
}
}
var getLeastNumbers = function(arr, k) {
if (!arr || arr.length === 0 || k === 0) return []
let result = [Infinity] // 堆从 1 开始算比较顺
for (let i = 0; i < arr.length; i++) {
heapify(result, arr[i], k + 1)
}
return result.slice(1)
}
3. 提交记录(仅供参考)
- 执行时间:104ms(打败了 90.51%)
- 内存消耗:40.9MB(打败了 100%)