我对此代码的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次,但我不确定
答案 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)
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为kT(n) = 2^lgnT(1) + lgn * n
T(n) = n + nlgn
nlgn比n增长得快,因此它是主导词。因此O(nlgn)