是否存在一种算法能够在O(log n)时间内找到未排序数组的最大值?
这个问题被问得很多(这是一个常见的CS作业问题吗?),答案总是一样的:不行。
从数学上考虑。除非数组已经排序,否则没有什么可以“切成一半”来给你log(n)
的行为。
阅读问题评论进行更深入的讨论(这可能超出了问题的范围)。
O(N) = O(Const * N) = O(N / Const) = O(N + Const) = O(N - Const)
另一方面,在实践中,分治并行算法可以带来一些性能上的好处,因此它可能会运行得更快。幸运的是,大O表示法不涉及这种细粒度的算法复杂度分析。
O(1)
的任务,只要我们不需要随后比较彼此之间的计算结果以找出最大值。比较是一个O(1)
操作,但需要重复进行N
次,因为没有办法不比较某些内容并仍然获得最大值。因此,无论核心数量如何,对于此任务来说,O(log n)
都是不可能的。 - oleksii不行。你至少需要遍历一次数组。
是的,我们可以这样做,但有一个条件,那就是我们的数组必须是山形数组。
public int peakIndexInMountainArray(int[] arr) {
int s = 0;
int e = arr.length-1;
int mid = s+(e-s)/2;
while(s<e){``
if(arr[mid]<arr[mid+1]){
s = mid+1;
}
else{
e = mid;
}
mid = s+(e-s)/2;
}
return mid;
}`
O(log n)
意味着您甚至不必读取整个数组,因为那将是 O(n)
,对于未排序的数组来说这并不真实,因为如果您无法将其与所有其他元素进行比较,则无法保证元素是否为最大值。 O(n)
是您可以获得的最佳绝对最大值,它仅遍历一次数组,如果您只想要一个近似值,则可以随机选择元素并拥有它们的最大值,这将选择少于 n
个元素,但对于未排序的数组而言,O(log n)
是不可能的。
有一种比 O(N)
更好的算法:
你只需要从数组中随机选择一个元素,并假设它是最大的。
不,说真的,如果你有一个正态分布的数字数组,并且你不需要得到最大的数字,而是一些接近最大的数字,那么你可以,比如说,随机选择 N/10 个元素并从中选择最大的。 对于正态分布,找到一个足够接近最大值的数字的机会是相当高的。或者你可能幸运地找到最大的数字,但你无法确定是否找到了。
我认为,在某些情况下,这种方法可能很有用。例如,如果你需要将数字分组到桶中,但又不想读取整个数组。在这种情况下,你可以随机选择10%的样本,并根据该样本的最大值加一个额外的桶来进行分组,用于存放超过该10%最大值的数字。这应该足够好了。
O(log(n) * log(m))
n
是要比较的数字的数量;m
是每个数字的大小。
然而,硬件尺寸将是:
O(n * m)
算法如下:
成对比较数字。这需要的时间为O(log(m))
,大小为O(n * m)
,使用进位前瞻比较器。
使用步骤1的结果来复用1的两个输入。这需要的时间为O(1)
,大小为O(n * m)
。
现在你有一个初始大小的一半的数组;回到步骤1。这个循环重复log(n)
次,所以总时间为O(log(n) * log(m))
,总大小为O(n * m)
。
通过添加一些MUX,您还可以跟踪最大数字的索引(如果需要),而不增加算法的复杂性。
k > n
时。 - Mysticialk
视为某个常量,因此忽略它。 (2)明确使用k
符号。我从未看过任何一本书/文章分析算法时假设核心数k = f(n)
为某个函数f
(当然除了常数)。如果有人这样做了,请引用这个来源,我会撤回我的评论。 - amitO(n)
,因此最终会得到O(n log n)
。Brent定理可能有助于一些算法级联(证明并不简单),但也许我误解了这个概念。请参见http://www.uni-graz.at/~haasegu/Lectures/GPU_CUDA/Lit/reduction.pdf幻灯片30。 - David TitarencoO(#processors x time complexity)
相关)或“深度”(与O(time complexity)
相关),因此我会推断出对于这个问题,如果充分限定,两者都是正确的想法。http://en.wikipedia.org/wiki/Sorting_network - Mooing Duck