【发布时间】:2013-09-12 02:27:34
【问题描述】:
我一直认为迭代搜索是在未排序列表中查找最大值的首选方法。
我的想法相当随意,但简而言之:我相信我可以在 O(logn) 时间内完成任务,其中 n 是输入数组的大小。
采用归并排序的方法:分而治之。
第一步:将 findMax() 任务分成两个子任务findMax(leftHalf) 和findMax(rightHalf)。这个划分应该在O(logn)时间完成。
第 2 步:合并两个最大的候选项。 此步骤中的每一层都应花费恒定时间这是错误的。每次比较都是在恒定时间内完成的,但是有O(1),并且根据上一步,O(logn) 这样的层。所以它也应该在O(1) * O(logn) = O(logn)时间完成(请原谅符号的滥用)。2^j/2 这样的比较需要完成(第 j 级的 2^j 对候选人)。
因此,整个任务应该在O(logn)时间完成。O(n)时间。
但是,当我尝试对其计时时,我得到的结果清楚地反映了线性 O(n) 运行时间。
大小 = 100000000 最大值 = 0 时间 = 556
大小 = 200000000 最大值 = 0 时间 = 1087
大小 = 300000000 最大值 = 0 时间 = 1648
大小 = 400000000 最大值 = 0 时间 = 1990
大小 = 500000000 最大值 = 0 时间 = 2190
大小 = 600000000 最大值 = 0 时间 = 2788
大小 = 700000000 最大值 = 0 时间 = 3586
怎么会?
这是代码(我未初始化数组以节省预处理时间,据我测试,该方法准确识别未排序数组中的最大值):
public static short findMax(short[] list) {
return findMax(list, 0, list.length);
}
public static short findMax(short[] list, int start, int end) {
if(end - start == 1) {
return list[start];
}
else {
short leftMax = findMax(list, start, start+(end-start)/2);
short rightMax = findMax(list, start+(end-start)/2, end);
return (leftMax <= rightMax) ? (rightMax) : (leftMax);
}
}
public static void main(String[] args) {
for(int j=1; j < 10; j++) {
int size = j*100000000; // 100mil to 900mil
short[] x = new short[size];
long start = System.currentTimeMillis();
int max = findMax(x);
long end = System.currentTimeMillis();
System.out.println("size = " + size + "\t\t\tmax = " + max + "\t\t\t time = " + (end - start));
System.out.println();
}
}
【问题讨论】:
标签: java max divide-and-conquer