跳转至

面试题 17.14. 最小 K 个数

题目描述

设计一个算法,找出数组中最小的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))

解法

方法一:排序

直接排序,取前 k 个数即可。

时间复杂度 $O(n\log n)$。其中 $n$ 为数组长度。

1
2
3
class Solution:
    def smallestK(self, arr: List[int], k: int) -> List[int]:
        return sorted(arr)[:k]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution {
    public int[] smallestK(int[] arr, int k) {
        Arrays.sort(arr);
        int[] ans = new int[k];
        for (int i = 0; i < k; ++i) {
            ans[i] = arr[i];
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        sort(arr.begin(), arr.end());
        vector<int> ans(k);
        for (int i = 0; i < k; ++i) {
            ans[i] = arr[i];
        }
        return ans;
    }
};
1
2
3
4
5
6
7
8
func smallestK(arr []int, k int) []int {
    sort.Ints(arr)
    ans := make([]int, k)
    for i, v := range arr[:k] {
        ans[i] = v
    }
    return ans
}
1
2
3
4
5
6
7
class Solution {
    func smallestK(_ arr: [Int], _ k: Int) -> [Int] {
        guard k > 0 else { return [] }
        let sortedArray = arr.sorted()
        return Array(sortedArray.prefix(k))
    }
}

方法二:优先队列(大根堆)

维护一个大小为 $k$ 的大根堆,遍历数组,将当前元素入堆,如果堆的大小超过 $k$,弹出堆顶元素。

遍历结束,将堆中元素的 $k$ 个元素取出即可。

时间复杂度 $O(n\log k)$。其中 $n$ 为数组长度。

1
2
3
4
5
6
7
8
class Solution:
    def smallestK(self, arr: List[int], k: int) -> List[int]:
        h = []
        for v in arr:
            heappush(h, -v)
            if len(h) > k:
                heappop(h)
        return [-v for v in h]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution {
    public int[] smallestK(int[] arr, int k) {
        PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> b - a);
        for (int v : arr) {
            q.offer(v);
            if (q.size() > k) {
                q.poll();
            }
        }
        int[] ans = new int[k];
        int i = 0;
        while (!q.isEmpty()) {
            ans[i++] = q.poll();
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        priority_queue<int> q;
        for (int& v : arr) {
            q.push(v);
            if (q.size() > k) {
                q.pop();
            }
        }
        vector<int> ans;
        while (q.size()) {
            ans.push_back(q.top());
            q.pop();
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func smallestK(arr []int, k int) []int {
    q := hp{}
    for _, v := range arr {
        heap.Push(&q, v)
        if q.Len() > k {
            heap.Pop(&q)
        }
    }
    ans := make([]int, k)
    for i := range ans {
        ans[i] = heap.Pop(&q).(int)
    }
    return ans
}

type hp struct{ sort.IntSlice }

func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (h *hp) Push(v any)        { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
    a := h.IntSlice
    v := a[len(a)-1]
    h.IntSlice = a[:len(a)-1]
    return v
}

评论