带递归的大O表示法

时间:2017-10-02 02:03:27

标签: java big-o

我对此代码的Big O表示法有疑问:

int strange_sumA(int[] arr) {
     if (arr.length == 1) {
        return arr[0];
        } else {
             int newlen = arr.length/2;
             int[] arrLeft = new int[newlen];
             int[] arrRight = new int[newlen];
         for (int i=0; i<newlen; i++) {
             arrLeft[i] = arr[i];
         }
         for (int i=newlen; i<arr.length-1; i++) {
             arrRight[i-newlen] = arr[i];
         }
         return strange_sumA(arrLeft) + strange_sumA(arrRight);
    }
}

根据我的理解,第一个for循环是O(n / 2),第二个for循环是O(n / 2),使整个第一次运行O(n)。然后,在第一次递归之后,接下来两次递归的大o仍然是O(n),因为2 [n / 2] = n,而下一次递归也是4 [n / 4] = n。那么,这个算法的整个大O符号是O(n ^ 2)吗?我认为代码会运行N次,但我不确定

3 个答案:

答案 0 :(得分:1)

进行运行时分析时,重要的是要考虑您正在测量的是什么。例如......看起来你正在对数组中的所有数字求和。但是,你不是在迭代地做 - 你是递归地做的。所以,如果你最贵的&#34;操作(花费最多时间的步骤)是函数调用...然后您可以选择表示在函数调用中测量的运行时间。

由于每次将数组分成两半,因此它是对数的。

O(log n)

现在,如果您还想考虑每个阵列操作。

arrLeft[i] = arr[i];

你做O(n / 2)次操作两次,所以O(n),为每个函数调用。因此每个函数调用都有O(n)数组操作。

O(n)

对于整个数组操作,我们必须将每个函数调用的数组操作乘以#函数调用次数。

O(n * log n) 

您也可以通过master theorm

证明这一点

答案 1 :(得分:0)

设p(n)是具有长度为n的数组的算法的时间复杂度。所以我们得到:

T(n)= 2T(n / 2)+ O(n)

T(n)= 2(2T(n / 4)+ n / 2)+ O(n)

...

T(n)= 2 ^(log_2(n))T(1)+ log_2(n)* O(n)= O(n)+ O(n)* log_2(n)= O(n log) n)的

答案 2 :(得分:0)

从T(n)= 2T(n / 2)+ n

开始
T(n/2) = 2T(n/4) + n/2

将其替换为原始

T(n) = 2[2T(n/4) + n/2] + n
T(n) = 2^2T(n/4) + 2n

再做一次

T(n/4) = 2T(n/8) + n/4

再次替换

T(n) = 2^2[2T(n/8) + n/4] + 2n
T(n) = 2^3T(n/8) + 3n

您可以根据需要重复,但最终会看到模式

T(n) = 2^kT(n/2^k) + kn

我们想要得到T(1)所以设置n / 2 ^ k = 1并求解k

n/2^k = 1 then,
lgn = k

现在以一般形式

替换lgn为k
T(n) = 2^lgnT(1) + lgn * n

T(n) = n + nlgn   

nlgn比n增长得快,因此它是主导词。因此O(nlgn)