当前位置: 首页 > 知识库问答 >
问题:

Java Stream distinct().sorted() 的时间复杂度是多少?

彭浩穰
2023-03-14

每次我接受编码面试时,我总是避免使用Java流,因为我不能很好地分析时间复杂性。

举个例子:在我的日常工作中,我可能会这样写:

Arrays.stream(a).distinct().sorted().toArray();

以获取唯一编号并对其进行排序

但我很好奇时间的复杂性会是..?是 distinct().sorted 会变成一个嵌套的循环?

我需要将它们分开吗?

int[] arr = Arrays.stream(a).distinct().toArray();
Arrays.stream(arr).sorted().toArray();

所以有时候当我接受采访时,我会使用set来区分然后对它们进行排序......但是我真的很想写一个干净的代码......

如果有人能帮忙!谢谢大家!

共有1个答案

锺离飞鸣
2023-03-14

不可能有明确的说法,因为你是针对一个接口进行开发的,而规范并没有要求特定的排序算法。

对于通用的流,我们必须假设一个比较排序,其最坏情况为O(n log n)是任何算法都无法避免的。

但您的示例使用的是IntStream,原则上可以使用计数排序或类似排序,具有O(n)。对于参考实现,这在实践中不会发生,因为在实践中,具有更好的最坏情况时间复杂性并不一定会导致更好的性能,并且元素的最大数量限制为JVM的最大数组大小。

准确度()的时间复杂度为O(n),因为它只是检查添加到HashSet中是否成功。将O(n)与O(n log n)组合导致整体复杂度为O(n log n)。也许面试官把时间复杂性的组合弄错了。

但这是一个很好的例子,表明时间复杂度并不等于性能。使用 sorted().distinct() 时,distinct() 操作将利用传入元素的排序特性,因此无需在后台构建 HashSet¹。由于参考实现没有设置基元值,因此这消除了大量的装箱开销。另一方面,使用 distinct().sorted() 可以减少要排序的元素数量,但它需要具有明显少于总流元素的独特元素才能获得回报。

这种性能差异不包括在时间复杂度中,这两种方法仍然相同。但是如前所述,对于原始类型的流,具有不同时间复杂度的不同算法是可能的。

但是有一件事,我们可以肯定地说。当您将操作拆分为两个流操作时,例如从第一个流请求结果数组并再次将其传递给Arrays.stream,底层实现不可能在下一个操作中利用有关上一个操作的知识。

请注意,上面的语句假设了一个终端操作,就像您的示例中的< code>toArray一样,它消耗所有元素,并要求维护生成的相遇顺序。对于其他短路或无序的终端操作,总的时间复杂度可能会改变,例如< code>sorted()。findFirst()可以优化为相当于< code>min()的值,或者可以取消无序终端操作的排序步骤,比如< code>sum()。这在当前的参考实现中不会发生,但是,如前所述,您是针对接口进行编程的。

对于原始流,这仅适用于Java

 类似资料:
  • 问题内容: 我当时在看这个pycon演讲,时间是34:30,发言人说,可以在中完成获取元素列表中最大的元素的操作。 那怎么可能?我的理解是,创建堆将是,但是其本身的复杂性是还是(以及(实际的算法是什么))? 问题答案: 扬声器在这种情况下是错误的。实际费用为。仅在可迭代的第一个元素上调用堆化。就是那个,但如果小于,则微不足道。然后,将所有剩余的元素一次通过添加到此“小堆”中。每次调用需要花费时间。

  • 问题内容: 我在Java类中有一个私有的LinkedList,并且经常需要检索列表中的最后一个元素。列表需要缩放,所以我试图确定在进行更改时是否需要保留对最后一个元素的引用(以实现O(1)),或者LinkedList类是否已经通过getLast()调用完成了此操作。 LinkedList.getLast()的big-O成本 是多少 , 有记载吗? (即,我是否可以依靠此答案,或者即使它是O(1),

  • 问题内容: 我写了以下课程: 然后,在我的方法中,我创建了一个,向其中添加了一些具有“ X”和“ angle”字段的对象。 然后,我使用: 这种排序方法的复杂性是什么? 问题答案: 您可能已经阅读了有关Collections排序的文档,但是这里适合您: 排序算法是一种修改的mergesort(如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。该算法提供了有保证的n log(n)性能。

  • 注:∈/ 意思是不在,我不能在代码中输入。 这个问题可能与一些帖子重复。 理解Dijkstra算法的时间复杂度计算 Dijkstra算法的复杂性 Dijkstras算法的复杂性 我读过它们,甚至读过Quora上的一些帖子,但仍然无法理解。我在伪代码中添加了一些注释,并试图解决它。我真搞不懂为什么它是O(E log V)

  • 主要内容:时间复杂度,空间复杂度《 算法是什么》一节提到,解决一个问题的算法可能有多种,这种情况下,我们就必须对这些算法进行取舍,从中挑选出一个“最好”的。 算法本身是不分“好坏”的,所谓“最好”的算法,指的是最适合当前场景的算法。挑选算法时,主要考虑以下两方面因素: 执行效率:根据算法所编写的程序,执行时间越短,执行效率就越高; 占用的内存空间:不同算法编写出的程序,运行时占用的内存空间也不相同。如果实际场景中仅能使用少量的内

  • 此处声明: TreeSet为add()/remove()/contains()提供了日志(n)时间复杂性保证。 但是使用二叉查找树,在最坏的情况下,二叉查找树可以有O(n)高度。log(n)复杂性如何“保证”?