计算大O复杂度

时间:2014-07-03 05:49:48

标签: algorithm recursion big-o

在最近的一次考试中,我们获得了一个函数,用于计算未排序的ArrayList中出现的双精度数(不是原始double,但项目出现两次的次数)。

我正确地确定Big 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)了。

任何解释都非常感谢,因为我一直在寻找过去的一个月,似乎无法完全掌握我所缺少的东西。谢谢。

1 个答案:

答案 0 :(得分:2)

1M的整数之和为((M+1) * M) / 2。这只是一个数学事实(通常通过归纳证明)。如果你不相信,试试一些例子。

算法的第一次传递执行N-1 compare s,每个递归级别少一compare,直到最后一级递归为1 compare。因此,比较的总数(对于所有递归级别)是从1N-1的整数之和。在公式中用N-1代替M会将比较的总数作为(N * (N-1)) / 2

从那里,它只是代数

(N * (N-1)) / 2 = (N * N - N) / 2 = ((N^2) / 2) - (N / 2)

将其分解的原因是因为big-O只关心具有最大指数的N。当然,big-O也不关心常量。所以你扔掉了(N / 2)并忽略了/ 2,答案是O( N ^ 2 ),这是最大的一个......'

好吧,别担心我对此事的看法,就是这样。