【发布时间】:2011-07-22 05:55:34
【问题描述】:
是否有一种算法方法可以在对数时间 ( O(logn) ) 中找到未排序数组的最小值?还是只能在线性时间内实现?我不想并行。
谢谢
迈克尔
【问题讨论】:
标签: arrays complexity-theory big-o minimum
是否有一种算法方法可以在对数时间 ( O(logn) ) 中找到未排序数组的最小值?还是只能在线性时间内实现?我不想并行。
谢谢
迈克尔
【问题讨论】:
标签: arrays complexity-theory big-o minimum
这不可能是线性时间,因为在 lg n 步骤中您只能检查 lg n 元素,并且因为它们是未排序的,所以这些值不包含关于数组中的其他值。
【讨论】:
如果列表未排序,则您的搜索必须至少是线性的。您必须至少查看每个项目一次,因为您未查看的任何内容可能比您已经看到的要少。
【讨论】:
你的意思是最小值?
这是线性的——你遍历你的数组,保存最不为人知的元素的位置(或值本身),然后将每个元素与之进行比较。是不是元素较低保存它。最后你有最小元素的位置(或值)。
我在 C++0x 中做了一个简短的例子:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> array({5, 3, 2, 7, 5, 1, 9});
int min = array[0];
std::for_each(array.cbegin(), array.cend(), [&min] (const int cur) {
min = std::min(cur, min);
});
std::cout << min;
}
你可以在Ideone执行它
【讨论】:
线性不是,但是如果使用某种修改过的快速排序,它可以比线性快于少于 10 个元素。我怀疑你正在寻找少于 10 个数组中的项目 :)
实现它的另一种方法是深入了解 SSE 指令的世界。
一个可以提供帮助的 OPCODE 是 CMPLEPS,它一次并行比较 4 个标量。
如果您不愿意在并行代码中执行此操作,但我严重怀疑您是否愿意使用 SSE 汇编指令。
【讨论】:
一般来说并行并没有帮助。如果您的处理器多于 n,并且 您不计算加载数据所需的时间,即 O(n) ,那么是的,您可以在对数时间内完成。但是假设每个处理器有 10 个数字。这需要一定的时间。现在让每个处理器有 20 个数字。在并行比较彼此的结果之前,每个处理器将花费两倍的时间来处理其数字。 O(n) + O(log n) = O(n)。
【讨论】:
你也可以有一个分而治之的递归算法,代码:
private static Integer array[];
private static Integer findMinimum(int startIndex, int endIndex){
//base case
if(startIndex + 1 == endIndex || startIndex == endIndex){
return array[startIndex] < array[endIndex] ? array[startIndex] : array[endIndex];
}
//recursive case
int a = findMinimum(startIndex, (startIndex + endIndex) / 2 );
int b = findMinimum( (startIndex + endIndex) / 2 + 1, endIndex);
return Math.min(a, b);
}
该算法的运行时间为:O(n)
但是,如果您有 N 个处理器(我知道这不是一个“有效”的现实世界场景,这仅对理论讨论感兴趣)。您可以进行并行计算并且运行时间为:O(log n)
因此,如果您想做一些并行计算,您可能想尝试这种方法。
【讨论】: