【发布时间】:2014-07-03 05:49:48
【问题描述】:
在最近的一次考试中,我们得到了一个函数来计算在未排序的 ArrayList 中出现了多少双精度(不是原始的 double,而是一个项目出现两次的次数)。
我正确地确定了大 O 复杂度为 O(N^2),但由于我错误地确定了全部复杂度,因此只获得了部分功劳。函数如下:
public static <T> int countDoubles(ArrayList<T> list, int index, Comparator<? super T> cmp) {
if (index >= list.size())
return 0;
int count = 0;
for (int i = index + 1; i < list.size(); i++) {
if (cmp.compare(list.get(index), list.get(i)) == 0)
count++;
}
return count + countDoubles(list, index + 1, cmp);
}
在他刚刚发布的考试解决方案中,他给出了这样的解释:
输入集合中有N项,方法调用自己 一遍又一遍地使用产生新索引 N 次的归约步骤 直到它到达基本情况(集合结束)。对于每个 递归框架有一个 for 循环,可以在其中少一个元素上工作 重复每一帧中的集合,直到它到达末尾 集合。所以有 N 个递归调用和 N -1 个步骤 第一次调用,第二次调用 N-2,第三次调用 N-3,依此类推,直到 到达数组的末尾。这种行为在 上限复杂度的术语,因为它将呈现以下 表达式:
T(N) = (N-1) + (N-2) + (N-3) + ... + 1 = N(N-1)/2 = ((N^2)/2) - (N/2) = O(N^2)
为了正确理解这一点,我尝试画出一个大小为 10 的简单数组,每次将其检查的大小减一。
[] [] [] [] [] [] [] [] [] []
[] [] [] [] [] [] [] [] []
[] [] [] [] [] [] [] []
[] [] [] [] [] [] []
[] [] [] [] [] []
[] [] [] [] []
[] [] [] []
[] [] []
[] []
[]
计算递归级别是有意义的N。算出每个元素产生 9 + 8 ... = 45 考虑到 100(N 个递归级别 * N 个元素)是 100,我不明白 N/2 来自哪里,更不用说 ((N^2)/2) - (N/2)。
非常感谢任何解释,因为我一直在寻找过去一个月,似乎无法完全掌握我所缺少的东西。谢谢。
【问题讨论】:
-
尝试阅读Master Theorem