面试题 17.14. 最小K个数

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题 17.14. 最小K个数相关的知识,希望对你有一定的参考价值。

面试题 17.14. 最小K个数


题目链接: 面试题 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))

题解

法一:排序
代码一:

class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        sort(arr.begin(), arr.end());
        vector<int> ans(k, 0);
        for (int i = 0; i < k; ++i){
            ans[i] = arr[i];
        }
        return ans;
    }
};

代码二:

class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        sort(arr.begin(), arr.end());
        return vector(begin(arr), begin(arr) + k);
    }
};


法二:快速选择
参考官方题解评论区梦璃夜·天星

思路:
使用nth_element
nth_element实际上是快速选择算法的实现
void nth_element (Iterator first, Iterator first+nth, Iterator last, Compare comp);

重新排列range [first,last)中的元素,使第n个位置的元素是按排序顺序在该位置的元素。

其他元素没有任何特定的顺序,
只是第n个元素之前的元素都不大于该元素,
而第n个元素后面的元素均不小于该元素。

代码一:

class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        nth_element(arr.begin(), arr.begin() + k, arr.end());
        return vector(arr.begin(), arr.begin() + k);
    }
};

代码二:

无序的话认准 快速选择 nth_element
前n个无序

要求有序就用 部分排序 partial_sort
前n个有序
class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        nth_element(begin(arr), begin(arr)+k, end(arr));
        return vector(begin(arr), begin(arr)+k);
    }
};

法三:自建堆

class Solution {
public:
    void maxHeapify(vector<int>& arr, int i, int heapSize){
        int l = 2 * i + 1, r = 2 * i + 2, cur = i;
        if (l < heapSize && arr[l] > arr[cur]){
            cur = l;
        }
        if (r < heapSize && arr[r] > arr[cur]){
            cur = r;
        }

        if (cur != i){
            swap(arr[cur], arr[i]);

            //调整堆的顺序
            maxHeapify(arr, cur, heapSize);
        }
    }
    void buildMaxHeap(vector<int>& arr, int heapSize){
        for (int i = heapSize / 2; i >= 0; --i){
            maxHeapify(arr, i, heapSize);
        }
    }
    vector<int> smallestK(vector<int>& arr, int k) {
        int n = arr.size();
        vector<int> ans;
        if (n == 0 || k == 0) return ans;

        //构建大根堆
        buildMaxHeap(arr, k);

        for (int i = k; i < n; ++i){
            if (arr[0] > arr[i]){
                swap(arr[0], arr[i]);

                //调整大根堆
                maxHeapify(arr, 0, k);
            }
        }

        for (int i = 0; i < k; ++i){
            ans.push_back(arr[i]);
        }
        return ans;
    }
};

法四:堆

class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        int n = arr.size();
        vector<int> ans(k, 0);
        if (n == 0 || k == 0){
            return ans;
        }

        priority_queue<int> Q;
        for (int i = 0; i < k; ++i){
            Q.push(arr[i]);
        }

        for (int i = k; i < n; ++i){
            if (Q.top() > arr[i]){
                Q.pop();
                Q.push(arr[i]);
            }
        }

        for (int i = 0; i < k; ++i){
            ans[i] = Q.top();
            Q.pop();
        }
        return ans;
    }
};

以上是关于面试题 17.14. 最小K个数的主要内容,如果未能解决你的问题,请参考以下文章

面试题 17.14. 最小K个数分治法

面试题 17.14. 最小K个数分治法

Leetcode刷题100天—面试题 17.14. 最小K个数(优先队列)—day27

Leetcode刷题100天—面试题 17.14. 最小K个数(优先队列)—day27

C++&Python描述 LeetCode 面试题 17.14. 最小K个数

LeetCode 面试题 17.14. 最小K个数(堆排,快排)/剑指 Offer 10- I. 斐波那契数列 /470. 用 Rand7() 实现 Rand10()(拒绝采样,学!!!)