Arrays.sort() 会增加时间复杂度和空间时间复杂度吗?
Posted
技术标签:
【中文标题】Arrays.sort() 会增加时间复杂度和空间时间复杂度吗?【英文标题】:Will Arrays.sort() increase time complexity and space time complexity? 【发布时间】:2014-04-29 13:51:36 【问题描述】:有一个数组相关的问题,要求时间复杂度为O(n),空间复杂度为O(1)。
如果我使用Arrays.sort(arr)
,并使用for
循环进行一次循环,例如:
public static int hello(int[]A)
Arrays.sort(A);
for(int i=0;i<A.length;i++)
....................
return ....;
所以循环将花费 O(n) 时间。我的问题是:Arrays.sort()
会花费更多时间吗?如果我使用Arrays.sort()
,这个时间复杂度还会是O(n)吗? Arrays.sort()
会占用更多空间吗?
【问题讨论】:
这并没有指定使用的排序算法,所以我看不出它是如何回答的。 @RobertHarvey:除非有人假设Arrays.sort()
使用了一些魔法,否则我认为关于它的最小时间复杂度的问题是完全可以回答的,不是吗?
它指定Arrays.sort
,所以无论使用哪种算法。很难分辨这是什么语言(猜测是 Java),但标准库排序几乎总是比较排序。
尽管下面的答案部分都在喋喋不休,但您的实际问题的答案是肯定的:在平均情况下,排序将花费比 O(n) 更长的时间。
假设你对 big-O 复杂度有足够的了解,你真的应该问“Arrays.sort
的时间和空间复杂度是多少?”,这确实是一个没有研究工作的问题,因为这个是相当有据可查的。
【参考方案1】:
我假设您在这里谈论的是 Java。
所以循环将花费 O(n) 时间,我的问题是 Arrays.sort() 会花费更多时间吗?
是的,Arrays.sort(int[])
在我所知道的所有 Java 标准库实现中,是基于比较的排序的示例,因此是 must have worst-case complexity Ω(n log n)。特别是,Oracle Java 7 使用双轴快速排序变体来处理整数重载,它实际上有 Ω(n2) 最坏的情况。
Arrays.sort() 会占用更多空间吗?
很可能它会使用 ω(1) 空间(这意味着另一个是,空间使用量不是 O(1))。虽然仅使用恒定的额外空间来实现基于比较的排序并非不可能,但它非常不切实际。
也就是说,在某些条件下,可以在线性时间内对特定类型的数据进行排序,例如:
http://en.wikipedia.org/wiki/Counting_sort http://en.wikipedia.org/wiki/Pigeonhole_sort http://en.wikipedia.org/wiki/Radix_sort对于输入整数的恒定范围(例如,如果 abs(A[i]) <= C
用于某个常数 C),那么计数排序和基数排序确实只使用 O(n) 时间和 O(1) 空间,所以这可能很有用。
【讨论】:
根据文档,theta(n log n) 的时间不正确,而 theta(1) 的空间不正确。我的帖子包含来自文档的信息。 @theSilentOne 我不知道你在说什么,但我想你不知道 Ω 是什么意思 表示下限。根据文档,n log n 不是下限。 如果我错了,请纠正我,但是说排序具有恒定空间的下限并不是特别有意义 - 这适用于每一个算法。 我们通常在理论 CS 中谈论最坏的情况,这是不可能的。 Big-O 用于说明上限,Omega 用于说明下限,这是我在这里想要做的【参考方案2】:根据java jvm 8 javadocs的Arrays.sort()方法:
排序算法是 Vladimir Yaroslavskiy、Jon Bentley 和 Joshua Bloch 的 Dual-Pivot Quicksort。该算法在许多数据集上提供 O(n log(n)) 性能,导致其他快速排序降低到二次性能,并且通常比传统(单轴)快速排序实现更快。
所以它会将你的时间复杂度从 O(n) 增加到 O(n log(n))
【讨论】:
【参考方案3】:最近的 JDK 中的 Arrays.sort(int[] a) 是使用 Dual-pivot Quicksort 算法实现的,该算法具有 O(n log n) 的平均复杂度并就地执行(例如不需要额外的空间)。
【讨论】:
实际上它至少需要 Ω(log n) 额外空间 哦,你说的应该是执行栈空间吧。你是对的,但我想问题是关于堆空间的。【参考方案4】:它超过 O(n) 时间并且需要超过 O(1) 空间。
Arrays.sort() 在 1.7 中使用了修改后的Timsort,这是一种相对较新开发的排序算法,它提供了复杂度 x 的排序,其中 O(n)
【讨论】:
你还没有完全说服我我的陈述“完全没有意义”,因为我很确定它们确实如此,但是你的 cmets 鼓励我再次回顾我的渐近复杂性。 @NiklasB.,我肯定会告诉你说它是“最快的排序”是不正确的。我最近读了一篇关于它的文章,它在许多情况下比快速排序或合并排序表现更好,因此,“最快”似乎不恰当。我相信您可能比我更了解渐近复杂性这一主题,但我知道我的 cmets 对任何非博士软件工程师都是有意义的,并且根据 Java 文档的说法是正确的。 @theSilentOne 让我们把它留给那个朋友,不要难过 @NiklasB。谢谢你,先生。我也删除了我幼稚的反对票 sheepish grin 在 Java 中,Arrays.sort(int[] a)
标准实现使用快速排序,而不是 Timsort
。基于对象的搜索,因为它是稳定的。参考:docs.oracle.com/javase/7/docs/api/java/util/… 和 docs.oracle.com/javase/7/docs/api/java/util/…。对象数组的稳定排序实现在 Java 中是强制性的。【参考方案5】:
既然你说的是Java语言,时间复杂度肯定会从O(n)增加到O(nlogn)。那是因为在 Java 8 中, Arrays.sort() 是在 Dual-pivot 快速排序算法中实现的,而不是 single pivot 。所以需要额外的时间。 O(1) 的空间复杂度是不可能的,因为它需要更多的空间,我猜是 O(n/2)。
【讨论】:
以上是关于Arrays.sort() 会增加时间复杂度和空间时间复杂度吗?的主要内容,如果未能解决你的问题,请参考以下文章
Arrays.sort() 和 Arrays.parallelSort() 之间的区别
我想反转一个 char 数组,为啥在使用 Arrays.sort(arr, Collections.reverseOrder()) 时它会失败? [复制]
java中排序函数sort()使用,Arrays.sort()和Collections.sort()