【堆、快速选择排序】探寻TopK问题的解决方案

目录

前言

什么是TopK问题

建堆——优先级队列

快速选择排序QuickSelect

快速选择排序的时间复杂度


前言

TopK问题在面试中常常被问到 —— 比如,在10亿个整数里,找出最大的前100个。在海量数据中查找出重复出现的元素或者去除重复出现的元素也是常考的问题。所以在对待TopK问题上,我们可不敢掉以轻心。下面,我们进入正题。

什么是TopK问题

TopK问题就是在一个数据集合中找出最大的前K个或者最小的前K个。在面试中遇到这个问题时,通常它的数据量很大,动不动就上亿或者海量数据。这就导致我们无法直接在内存中对所有数据进行排序或者说排序的时间成本很高等等,因此这类问题通常不采取直接排序再查找的做法。下面我们看看几种常见的做法。

建堆——优先级队列

以这道题为例——在10亿个整数里,找出最大的前100个。下面我们看看堆是如何解决这个问题的。

用100个数建一个小堆,然后将剩余数据依次与堆顶元素比较,比堆顶数据大的则替换堆顶数据进堆,遍历完剩余的数据后,堆里面的值就是最大的前100个。会有同学在这里可能有这样的疑问——第50大的数据在堆顶时会不会挡住第51大、第52大的数据进堆。当然是不会的。如果第50大的数据经过向下调整后在堆顶,那么说明堆里面剩下的99个数都要比第50大的数大。仔细体会一下,这是不是很荒谬——第50大数据:我都已经是第50大了,居然还有99个数比我还大,看不起谁呢?!所以说前100大的数据是不会被挡住的。

我们先来重温优先级队列priority queue,下面是摘自文档的关于priority queue的解释:

Priority queues are a type of container adaptors, specifically designed such that its first element is always the greatest of the elements it contains, according to some strict weak ordering criterion.

可以看出,priority queue默认情况下是大堆,而我们这里需要一个小堆,故需要我们自己写一个比较方法。下面我们开始写代码:

#include <iostream>
#include <queue>
using namespace std;

#define N 10000  //数据个数
#define K 10	 //要找的前K个

//比较方法——因为默认是大堆,而我们的需求是小堆,故需传比较方法
struct MyGreater
{
	bool operator()(const int& left, const int& right)
	{
		return left > right;
	}
};

//造数据
void
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值