[路飞][LeetCode]面试题 17.14. 最小K个数

175 阅读2分钟

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

看一百遍美女,美女也不一定是你的。但你刷一百遍算法,知识就是你的了~~

谁能九层台,不用累土起!

题目地址

题目

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]

提示:

  • 0 <= len(arr) <= 100000
  • 0 <= k <= min(100000, len(arr))

解题思路

  • 常规操作,暴力解yyds

  • 我们使用sort排序,然后截取0-k的数返回

解题代码

var smallestK = function(arr, k) {
    return arr.sort((a,b)=>a-b).splice(0,k)
};

使用大顶堆

先回顾一下大顶堆的概念

大顶堆:每个结点的值都大于或等于其左右子结点的值。

如果是排序,求升序用大顶堆,求降序用小顶堆。

本题要求的是最小的k个,符合大顶堆。

我们来维护一个大小为k的大顶堆。

  • 如果 k0,我们直接返回空数组

  • 遍历arr数组,如果当前顶堆不满k个时,将遍历到的元素塞入队列

  • 否则,就判断当前元素是否小于堆顶的元素

  • 如果小于堆顶的元素,我们将堆顶的元素出队,将这个元素入队

var smallestK = function(arr, k) {
    if(!k) return [] // 排除 k===0 的情况 我们直接返回空数组
    const maxQueue = new MaxPriorityQueue()

    arr.forEach(v=>{ //遍历arr数组
        if(maxQueue.size()<k){  // 如果当前顶堆不满k个时,将遍历到的元素塞入队列
            maxQueue.enqueue(v)
        }else if(maxQueue.front().priority>v){ // 将堆顶的元素与遍历到的值进行比较,判断当前元素是否小于堆顶的元素
                maxQueue.dequeue()  // 堆顶的元素出堆
                maxQueue.enqueue(v)  // 当前元素入队
        }
    })

    return maxQueue.toArray().map(v=>v.element)
    
    // 需要注意的是,大顶堆转为数组后的格式是形如
    // [ { priority: 1, element: 1 } ] 而其中的 element才是实际的值 我们需要利用map取出
};

如有任何问题或建议,欢迎留言讨论!