[路飞] 最小 k 个数

100 阅读1分钟

记录 1 道算法题

最小 k 个数

leetcode-cn.com/problems/sm…


和第 k 小的数类似,可以用堆和排序进行解题。因为题目没要求按照升序或者降序返回,所以都差不多。

堆的话只要把堆内的数组返回就可以了,使用大顶堆。堆的实现可以看其他的文章

    function smallestK(arr, k) {
        const heap = new Heap((a, b) => b - a)
        for (let i = 0; i < k; i++) {
            heap.push(arr[i])
        }
        for (let i = k; i < arr.length; i++) {
            const n = arr[i]
            if (heap.data[0] > n) {
              heap.pop()
              heap.push(n)
            }
        }
        return heap.data
    }

排序的话有很多方法,这里使用快排。快排主要是找一个基准,然后分成左右两拨,进行递归处理。优化的方式是减枝,因为我们只需要排序 k 之前的数就可以了。

    function smallestK (arr, k) {
        fastSort(arr, 0, arr.length, k)
        return arr.slice(0, k)
    }
    
    function fastSort(arr, start, end, k) {
        if (start >= end) return
        // 用随机的一个基准会比较好,这里固定使用第一个数
        const p = arr[start]
        let s = start + 1
        
        for(let i = start + 1; i <= end) {
            if (arr[i] < p) {
                swap(arr, i, s)
                s++
            }
        }
        
        swap(arr, s - 1, start)
        if (s > k) {
            fastSort(arr, start, s - 1, k)
        } else if (s === k) {
            return
        } else {
            fastSort(arr, s, end, k)
        }
    }
    
    function swap(arr, a, b) {
        const t = arr[a]
        arr[a] = arr[b]
        arr[b] = t
    }