我考虑了两种计算数组最大/最小值的方法。
首先:
public class Extrema {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
double[] arr = new double[] { -0.11112, -0.07654, -0.03902, 0.0,
0.03902, 0.07654, 0.11112, 0.14142, 0.1663, 0.18478, 0.19616 };
double max = Double.NEGATIVE_INFINITY;
// Find out maximum value
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
}
}
第二种方法是对数组进行预排序,然后将arr [0]作为最小值,将te数组的最后一个条目作为最大值。
我知道最快的排序算法是0(n log n)。 第一种方法的循环将花费0(n)时间。但是通过n次比较,最糟糕的是n次写入操作。 由于Java中的时间测量不是真的可信,因此需要将这个问题正式化...... 我更喜欢第一种方法..我是对的吗?特别是如果我需要两个极值,因此需要&lt; =n²写入操作。 使用相同的数组预排序的方法调用数量是多少? 最好的祝福, Jan
答案 0 :(得分:2)
首先,提供足够大的输入,时间测量就足够了。
其次,在您的示例代码中,比较和写操作都不重要。大部分时间都花在访问大型阵列上(整个问题仅与包含数百万个元素的大型数组相关)在内存中并将其移动到CPU缓存中。
第三,如果你想要两个极值,最好只通过你的阵列一次。这相当于2 * n比较(与n ^ 2无关),并且仍然通过访问内存中的数组数据而占据主导地位。
如果您需要多次使用相同阵列的最大/最小值,只需存储它并且不要每次都计算它。除非你需要在另一个地方对你的数组进行排序的veriant(或者你可以预先输出一次并且每次运行程序都会运行),所以排序得到min / max是没有意义的。
答案 1 :(得分:1)
第一种方法的计算复杂度O(n)
,第二种方法就像你说的那样O(n*log(n))
。但请记住,这种渐近复杂性忽略了常数因素,因此很容易就是线性算法实际上比n*log(n)
慢。在你的特定情况下,你不能比简单的迭代更好,这实际上是最好的解决方案。
仍然有趣的是,有一种线性算法可以找到基于qsort分区的序列中的第k个元素。该算法内置于C ++的stl中。如果您有兴趣,可以查看here。
如果数组永远不会更改并且您有许多查询,则第一种方法至少与第二种方法一样快 - 只需缓存第一次查询中找到的值。
答案 2 :(得分:0)
只是一个想法..
无论您选择哪种搜索算法,都可以随时利用多线程。比如说数组大小= 10,你可以产生两个线程1. thread-1会在数组的前半部分进行搜索,2。线程-2会在数组的后半部分进行搜索3.然后最后你比较这两个线程的结果来决定结果。
如果您选择考虑使用多线程来加速搜索,则必须考虑几个因素,例如最佳线程数(导致大量线程会导致大部分时间花在上下文切换中),堆栈可用性等。