面试题40. 最小的k个数

面试题40. 最小的k个数

问题描述:

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

解题思路:

这题不要直接使用 sort(arr.begin(), arr.end() ) 函数;

  • 时间复杂度:O(n\log n)O(nlogn),其中 nn 是数组 arr 的长度。算法的时间复杂度即排序的时间复杂度。
  • 空间复杂度:O(\log n)O(logn) ,排序所需额外的空间复杂度为 O(\log n)O(logn)

这题的目的不是使用sort函数;

使用大根堆进行维护k个数,然后进行比较最大值。

具体思路如下注释:

//我们用一个大根堆实时维护数组的前 k 小值。首先将前 k 个数插入大根堆中,随后从第 k+1 个数开始遍历,//如果当前遍历到的数比大根堆的堆顶的数要小,就把堆顶的数弹出,再插入当前遍历到的数。最后将大根堆里的数存入数组返回即可。//在下面的代码中,由于 C++ 语言中的堆(即优先队列)默认为大根堆,我们可以这么做。
class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k)   {
        vector<int>vec(k, 0);
        if (k == 0) return vec; // 排除 0 的情况
        priority_queue<int>Q;  //默认是大根堆(堆顶为最大值)     //等同于 priority_queue<int, vector<int>, less<int> > a;  //大根堆     //priority_queue<int, vector<int>, greater<int> > c;  //小根堆(堆顶为最小值)
    for (int i = 0; i < k; ++i)         Q.push(arr[i]);
        for (int i = k; i < (int)arr.size(); ++i)      {
            if (Q.top() > arr[i])         {
                Q.pop();
                Q.push(arr[i]);
             }
        }
        for (int i = 0; i < k; ++i)      {
            vec[i] = Q.top();
            Q.pop();
        }
        return vec;
    }
};
//复杂度分析
//时间复杂度:O(n\log k)O(nlogk),其中 n 是数组 arr 的长度。由于大根堆实时维护前 kk 小值,//所以插入删除都是 O(\log k)O(logk) 的时间复杂度,最坏情况下数组里 nn 个数都会插入,所以一共需要 O(n\log k)O(nlogk) 的时间复杂度。
//空间复杂度:O(k)O(k),因为大根堆里最多 k 个数。

原文地址:https://www.cnblogs.com/Tavi/p/12530810.html

时间: 2024-10-04 17:30:47

面试题40. 最小的k个数的相关文章

【面试题030】最小的k个数

[面试题030]最小的k个数 题目: 输入n个整数,找出其中最小的k个数. 例如输入4.5.1.6.2.7.3.8这8个字,则其中最小的4个数字是1.2.3.4. 思路一: 可以同样的基于随机快速排序的Partition函数,来对数组做划分, 基于k来作调整,返回调用Partition函数,直到左边的k个数字是整个数组中最小的k个数字. ps.这种方法要修改数组中数字的顺序,因为Partition函数会调整数组中数字的顺序. 12345678910111213141516171819202122

剑指Offer面试题30(java版):最小的k个数

题目:输入n个整数,找出其中最小的k个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4 这道题最简单的思路莫过于把输入的n个整数排序,排序之后位于最前面的k个数就是最小的k个数.这种思路的时间复杂度是O(nlogn),面试官会提示我们还有更快的算法. 解法一:O(n)的算法,只有当我们可疑修改输入的数组时可用 从上一题中我们可以得到启发,我们同样可以基于Partition函数来解决这个问题.如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数

【剑指offer】40、最小的K个数

题目 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 思路一 基于partition,当 index正好为k的时候,就是第k大的数.时间复杂度O(n) 缺点:需要改变数组 class Solution { public: int Partition(vector<int>& input, int begin, int end) { int low = begin, high = end; int pivot =

小米笔试题:无序数组中最小的k个数

题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来源:牛客网 无序数组中最小的k个数 对于一个无序数组,数组中元素为互不相同的整数,请返回其中最小的k个数,顺序与原数组中元素顺序一致. 给定一个整数数组A及它的大小n,同时给定k,请返回其中最小的k个数. 测试样例: [1,2,4,3],4,2 返回:[1,2] 代码 需要保留K个较小的元素,可以删

剑指Offer对答如流系列 - 最小的k个数

面试题40:最小的k个数 题目描述 输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 问题分析 最容易想到的方法就是排序,取相应数字的元素即可.我这里为了方便直接使用了快排来做这个. 想拉开与别人的差距,难免需要优化时间效率,我们可以这样做:依次遍历n个整数,用一个容器存放最小的k个数字,每遇到比容器中最大的数字还小的数字时,将最大值替换为该数字.容器可以使用最大堆或者红黑树来实现.堆相比红黑树更容易实现,我们这里采用堆.

找到无序数组中最小的k个数

题目:给定一个无序整数数组arr,找到其中最小的k个数 要求:如果数组arr的长度为n,排序之后自然可以得到最小的k个数,此时时间复杂度与排序的时间复杂度相同均为O(NlogN),本题要求实现时间复杂度为O(NLogK). 1.O(NLogK)的方法,即一直维护一个有k个数的最大的大根堆,这个堆是目前选出的k个最小数,在堆里的k个元素中堆顶的元素是最大的一个. 接下来遍历整个数组,遍历的过程中看当前数是否比堆顶元素小.如果是,就把堆顶的元素替换成当前的数,然后从堆顶的位置调整堆,替换后堆的最大元

找出最小的k个数

•已知数组中的n个正数,找出其中最小的k个数. •例如(4.5.1.6.2.7.3.8),k=4,则最小的4个数是1,2,3,4 •要求: –高效: –分析时空效率 •扩展:能否设计出适合在海量数据中实现上述运算? 方法一: 1 //利用最大根堆实现最小k个节点 2 //最大根堆特点:每个节点都比他左右孩子要大 3 //调整最大堆的时间复杂度为O(lnK),因此该算法(问题)时间复杂度为O(nlnK). 4 //思路:通过数组建堆 5 //规律:第i个节点的左孩子为2i+1,右孩子为2i+2 6

最小的K个数

输入n个数,找出其中最小的k个数.例如输入4,5,1,6,2,7,3,8 这8个数,则最小的4个数是1,2,3,4. 解法一:O(n)的算法,只有当我们可以修改输入数组时可用 1 int Partitoin(int* input, int low, int high) 2 { 3 if (input == NULL || low < 0 || high < 0 || low > high) 4 { 5 return -1; 6 } 7 int temp = input[low]; 8 w

【算法】数组与矩阵问题——找到无序数组中最小的k个数

1 /** 2 * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) 3 * 过程: 4 * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 5 * 在堆里的k个元素中堆顶的元素是最小的k个数中最大的那个. 6 * 2.接下来,遍历整个数组,遍历过程中看当前数是否比堆顶元素小: 7 * 如果是,就把堆顶元素替换成当前的数,然后从堆顶的位置调整整个堆,让替 8 * 换操作后堆的最大元素继续处在堆顶的位置: 9 * 如果不是,则不进行任何操作,继续遍历下一个数: 10 *