力扣 0040 - 最小的 k 个数

题目详情:最小的 k 个数

1. 思路

一种思路是利用快速排序,然后取前 k 个数。

另一种思路是构建一个大顶堆。数组中的数字依次进入大顶堆,当堆的长度小于 k k k 的时候,则加入堆尾,然后自底向上进行堆调整;当堆的长度大于等于 k k 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%)

你可能感兴趣的:(日拱一算法)