我最近在一次面试中进行了一次编码测试.我被告知:

有一个int万个未排序的大array.用户希望检索K个最大的元素.您将实现什么算法?

在这期间,有人强烈暗示我需要对数组进行排序.

所以,我建议使用内置sort(),或者如果性能真的很重要,可以使用自定义实现.然后我被告知,使用Collectionarray来存储k个最大的for循环,可能会达到大约O(N)个,事后来看,我认为是O(N*k)个,因为每次迭代都需要与K大小的数组进行比较,以找到要替换的最小元素,而对数组进行排序的需要会导致代码至少为O(N log N).

然后我回顾了这个链接,建议优先队列为K个数字,每次发现较大的元素时,删除最小的数字,也就是O(N log N)个.Write a program to find 100 largest numbers out of an array of 1 billion numbers

for循环方法坏吗?我应该如何证明使用for循环或priorityqueue/排序方法的优缺点?我认为,如果已经对数组进行了排序,则不需要再次遍历整个数组,也就是说,如果对排序后的数组调用了其他检索方法,则应该是常数时间.在运行实际代码时,是否有一些性能因素是我在建立伪代码理论时没有考虑的?

推荐答案

另一种解决方法是使用Quickselect.这将使您的总平均时间复杂度为101.考虑一下:

  1. 使用Quickselect(O(n))查找第k大数字x
  2. 再次遍历数组(或仅遍历右侧分区)(O(n))并保存所有元素≥ x
  3. 返回保存的元素

(如果有重复的元素,可以通过计算需要添加到结果中的x个重复元素的数量来避免重复.)

您的问题与您链接的SO问题中的问题之间的区别在于,您只有一百万个元素,因此它们肯定可以保存在内存中,以便正常使用Quickselect.

Java相关问答推荐

在未跨多次运行重写过go 的数据的情况下将数据写入到SON文件时遇到问题(使用Jackson)

Spring Boot找不到Mapper bean

如果它最终将被转换为int类型,为什么我们在Java中需要较小的integer类型?

如何计算内循环的时间复杂度?

如何粘合(合并)文件Lucene?

Java函数式编程中的双值单值映射

如何以干净的方式访问深度嵌套的对象S属性?

R.id.main给我一个红色错误,无法解析MainActivity.java中的符号main

将关键字与正文中的_Allowed匹配,但带有__Signing可选后缀

Com.example.service.QuestionService中的构造函数的参数0需要找不到的类型为';com.example.Dao.QuestionDao;的Bean

按属性值从流中筛选出重复项

OpenGL ES 3.0-纹理黑色

是否为计划任务补偿系统睡眠?

Java中不兼容的泛型类型

我可以在@Cacheable中使用枚举吗

如何在Java springboot中从一个端点发送多个时间响应?

泛型与泛型问题的完美解决方案?

如何在ApacheHttpClient 5中为单个请求设置代理?

基于距离的APACHE POI公式判断

转换为JSON字符串时,日期按天递减-Java