87 前K大数(Top k Largest Numbers)

1 题目

题目:前K大数(Top k Largest Numbers)
描述:在一个数组中找到前K大的数。

lintcode题号——544,难度——medium

样例1:

输入: [3, 10, 1000, -99, 4, 100] 并且 k = 3
输出: [1000, 100, 10]

样例2:

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

2 解决方案

2.1 思路

  该题可以用quick select的算法来将小于k的数都移到左边,再用quick sort快排进行排序。
  也可以考虑使用优先序列来做,维护一个容量为k的优先序列,需要取前k个数,每次取完序列顶部再弹出,进行k次即可。

2.3 时间复杂度

  使用quick select的方式,移动小于k的值到左边耗时O(n),对左边的k个数排序耗时O(k * log k),总时间复杂度为O(n + k * log k)。
  使用优先序列的方式,将元素放入序列耗时O(log k),需要进行n次,将元素弹出序列耗时O(logk),需要进行k次,总时间复杂度O(n * log k) +O(k * log k) = O(n * log k);

在k趋近于n的时候,两种排序方式的耗时相近。

2.4 空间复杂度

  使用quick select的方式,空间复杂度为O(1)。
  使用优先序列的方式,需要一个容量为k的最小堆优先序列,所以空间复杂度为O(k)。

3 源码

细节:

  1. 使用优先序列的方式,建立一个最小堆优先序列,每次弹出堆顶的最小元素,保留k个较大的元素。
  2. 因为是最小堆优先序列,组装结果的时候需要按照弹出顺序的倒序来组装。

C++版本:

/**
* @param nums: an integer array
* @param k: An integer
* @return: the top k largest numbers in array
*/
vector<int> topk(vector<int> &nums, int k) {
    // write your code here
    vector<int> result;
    if (nums.size() < k)
    {
        return result;
    }

    priority_queue<int, vector<int>, greater<int>> numQueue; // 最小堆优先序列
    for (auto it : nums)
    {
        numQueue.push(it);
        if (numQueue.size() > k) // 弹出多余的数
        {
            numQueue.pop();
        }
    }

    for (int i = 0; i < k; i++)
    {
        result.insert(result.begin(), numQueue.top()); // 倒序组装结果
        numQueue.pop();
    }

    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值