此代码的复杂性是什么?我们是否应该总结复杂性

What will be the complexity of this code? Should we sum complexities?

本文关键字:复杂性 是否 代码 是什么 我们      更新时间:2023-10-16

我有一个算法,首先对向量进行排序,然后遍历其元素并XOR它们。我应该将排序和 for 循环的复杂性相加以计算整体算法复杂性吗?所以,我有下一个代码:

std::sort(array.begin(), array.end());
for (int i =1; i < array.size(); ++i) {
  result = array[i-1]^array[i];
}

我们有一个 for 循环,它O(N)复杂度和std::sort平均具有O(N log N)比较。那么下一个代码的复杂性将O(N + N log N) ?或者在这种情况下,我们只需要选择最高的时间复杂度类,即线性时间O(N log N),并且不对它们求和?

运行时受排序步骤的限制,O(nlgn) .for 循环可能具有O(n)复杂性,但整个运行时始终由最高功率主导。有关数学证明,请参见此处:

https://math.stackexchange.com/questions/324200/big-o-notation-sum-rule

是的,你可以对它们求和:O(n)O(n log n)变得O(n + n log n) . 但请注意,这不是您所建议的O(2n log n),因为加法是在基本算术中的乘法之后进行的。

现在,正如O(1 + n)总是简化为O(n)一样,您的O(n + n log n)将减少到O(n log n),因为单独n项小于n log n项,而大O表示法始终是关于极限,而不是确切的方程。

有些人可能会发现更直观地从一开始就认识到O(n)是由O(n log n)主导的,并且从一开始就从不对它们求和。 这是一个有用的心理捷径,但两种观点都能给你带来相同的结果。

复杂度类O(N)是类O(N log N)的子集,因为log N > 1足够高的N。因此,代码O(N + N log N)的复杂性类是O(2 N log N)的子集,并且由于复杂性类是不变的w.r.t.常量,因此在末尾O(N log N)

我们计算复杂性的方法是在所有复杂度中选择最高的。

因此,假设您有以下代码

for i in range 0 to n
{
    for  in range 0 to n
    {
        \ code
    }
}
for i in range 0 to n
{
    \ code
}

所以,这里的复杂性会O(n^2) + O(n).最终会O(n^2).所以,上面整个代码的复杂性是O(n^2)的。


同样,在您的情况下,复杂度是O(N log N) + O(N) ,这使得最终的复杂性是O(N log N)

首先

O(N+N log N)不会给你O(2N log N),它会给你O( (log N+1) * N)。 这个算法将以O(N log N)为界,因为当N接近无穷大时,它的增长速度比O(N)快。