Algorithm 大O,你如何计算/近似它?

Algorithm 大O,你如何计算/近似它?,algorithm,optimization,complexity-theory,big-o,performance,Algorithm,Optimization,Complexity Theory,Big O,Performance,大多数拥有计算机科学学位的人肯定知道什么。 它有助于我们衡量算法的伸缩性 但我很好奇,您如何计算或近似算法的复杂性?熟悉我使用的算法/数据结构和/或快速浏览迭代嵌套分析。困难在于当您调用库函数时,可能多次调用—您常常无法确定您是否在不必要的时候调用了该函数,或者他们正在使用什么实现。也许库函数应该有一个复杂度/效率度量,无论是大O还是其他度量,都可以在文档中找到,甚至可以在文档中找到。熟悉我使用的算法/数据结构和/或快速浏览迭代嵌套分析。困难在于当您调用库函数时,可能多次调用—您常常无法确定您是

大多数拥有计算机科学学位的人肯定知道什么。 它有助于我们衡量算法的伸缩性


但我很好奇,您如何计算或近似算法的复杂性?

熟悉我使用的算法/数据结构和/或快速浏览迭代嵌套分析。困难在于当您调用库函数时,可能多次调用—您常常无法确定您是否在不必要的时候调用了该函数,或者他们正在使用什么实现。也许库函数应该有一个复杂度/效率度量,无论是大O还是其他度量,都可以在文档中找到,甚至可以在文档中找到。

熟悉我使用的算法/数据结构和/或快速浏览迭代嵌套分析。困难在于当您调用库函数时,可能多次调用—您常常无法确定您是否在不必要的时候调用了该函数,或者他们正在使用什么实现。也许库函数应该有一个复杂度/效率度量,无论是大O还是其他度量,都可以在文档中找到,甚至可以在文档中找到。

将算法分解成您知道的大O符号,并通过大O运算符组合。这是我知道的唯一方法


有关更多信息,请查看主题上的。

将算法分解为您知道的大O表示法,并通过大O运算符组合。这是我知道的唯一方法


有关更多信息,请查看主题。

大O给出了算法时间复杂度的上限。它通常与处理数据集(列表)结合使用,但也可以在其他地方使用

下面是一些在C代码中如何使用它的示例

假设我们有一个由n个元素组成的数组

int array[n];
如果我们想要访问数组的第一个元素,这将是O(1),因为不管数组有多大,总是需要相同的恒定时间来获取第一个项目

x = array[0];
如果我们想在列表中找到一个数字:

for(int i = 0; i < n; i++){
    if(array[i] == numToFind){ return i; }
}
for(int i=0;i
这将是O(n),因为我们最多需要查看整个列表才能找到我们的号码。Big-O仍然是O(n),尽管我们可能会在第一次尝试时找到我们的数字,并在循环中运行一次,因为Big-O描述了算法的上界(ω表示下界,θ表示紧界)

当我们进入嵌套循环时:

for(int i = 0; i < n; i++){
    for(int j = i; j < n; j++){
        array[j] += 2;
    }
}
for(int i=0;i
这是O(n^2),因为对于外环(O(n))的每一次传递,我们必须再次遍历整个列表,因此n的乘积为n的平方


这仅仅是触及表面,但当你开始分析更复杂的算法时,涉及证明的复杂数学就开始发挥作用。希望这至少能让您熟悉基本知识。

大O给出了算法时间复杂度的上限。它通常与处理数据集(列表)结合使用,但也可以在其他地方使用

下面是一些在C代码中如何使用它的示例

假设我们有一个由n个元素组成的数组

int array[n];
如果我们想要访问数组的第一个元素,这将是O(1),因为不管数组有多大,总是需要相同的恒定时间来获取第一个项目

x = array[0];
如果我们想在列表中找到一个数字:

for(int i = 0; i < n; i++){
    if(array[i] == numToFind){ return i; }
}
for(int i=0;i
这将是O(n),因为我们最多需要查看整个列表才能找到我们的号码。Big-O仍然是O(n),尽管我们可能会在第一次尝试时找到我们的数字,并在循环中运行一次,因为Big-O描述了算法的上界(ω表示下界,θ表示紧界)

当我们进入嵌套循环时:

for(int i = 0; i < n; i++){
    for(int j = i; j < n; j++){
        array[j] += 2;
    }
}
for(int i=0;i
这是O(n^2),因为对于外环(O(n))的每一次传递,我们必须再次遍历整个列表,因此n的乘积为n的平方


这仅仅是触及表面,但当你开始分析更复杂的算法时,涉及证明的复杂数学就开始发挥作用。希望这至少能让你熟悉基本知识。

看到这里的答案,我想我们可以得出结论,我们中的大多数人确实可以通过查看算法并使用常识来近似算法的顺序,而不是像在大学时所想的那样,使用常识来计算。 话虽如此,我必须补充的是,即使是教授也鼓励我们(稍后)认真思考它,而不是仅仅计算它

另外,我想补充一下递归函数的实现方法:

假设我们有一个类似()的函数:

它递归地计算给定数字的阶乘

第一步是尝试并确定函数体的性能特征。仅在这种情况下,函数体中不做任何特殊操作,只进行乘法(或返回值1)

因此身体的性能是:O(1)(常数)

接下来,尝试并确定递归调用的数量。在这种情况下,我们有n-1个递归调用

因此递归调用的性能是:O(n-1)(顺序是n,因为我们丢弃了不重要的部分)

然后将这两个函数放在一起,就可以得到整个递归函数的性能:

1*(n-1)=O(n)


,来回答我在这里描述的方法实际上处理得很好。但请记住,这仍然是一个近似值,并不是一个完整的数学正确答案。这里描述的方法也是我们在大学里教过的方法之一,如果我记得correc的话
Number_Of_Steps = f(N)
Number_Of_Steps = f(data.length)
f(N) = C + ??? + C
f(N) = C + (C + C + ... + C) + C = C + N * C + C
f(N) = 2 * C * N ^ 0 + 1 * C * N ^ 1
f(N) = 1 + N ^ 1
O(N)
for (i = 0; i < 2*n; i += 2) {  // 1
    for (j=n; j > i; j--) {     // 2
        foo();                  // 3
    }
}
f(N) = Summation(i from 1 to 2 * N / 2)( ... ) = 
     = Summation(i from 1 to N)( ... )
f(N) = Summation(i from 1 to N)( Summation(j = ???)(  ) )
f(N) = Summation(i from 1 to N)( Summation(j = 1 to (N - (i - 1) * 2)( C ) )
f(N) = Summation(i from 1 to N / 2)( Summation(j = 1 to (N - (i - 1) * 2)) * ( C ) ) + Summation(i from 1 to N / 2) * ( C )
f(N) = Summation(i from 1 to N / 2)( (N - (i - 1) * 2) * ( C ) ) + (N / 2)( C )

f(N) = C * Summation(i from 1 to N / 2)( (N - (i - 1) * 2)) + (N / 2)( C )

f(N) = C * (Summation(i from 1 to N / 2)( N ) - Summation(i from 1 to N / 2)( (i - 1) * 2)) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - 2 * Summation(i from 1 to N / 2)( i - 1 )) + (N / 2)( C )

=> Summation(i from 1 to N / 2)( i - 1 ) = Summation(i from 1 to N / 2 - 1)( i )

f(N) = C * (( N ^ 2 / 2 ) - 2 * Summation(i from 1 to N / 2 - 1)( i )) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - 2 * ( (N / 2 - 1) * (N / 2 - 1 + 1) / 2) ) + (N / 2)( C )

=> (N / 2 - 1) * (N / 2 - 1 + 1) / 2 = 

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

   ((N ^ 2 / 4) - (N / 2)) / 2 = 

   (N ^ 2 / 8) - (N / 4)

f(N) = C * (( N ^ 2 / 2 ) - 2 * ( (N ^ 2 / 8) - (N / 4) )) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - ( (N ^ 2 / 4) - (N / 2) )) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - (N ^ 2 / 4) + (N / 2)) + (N / 2)( C )

f(N) = C * ( N ^ 2 / 4 ) + C * (N / 2) + C * (N / 2)

f(N) = C * ( N ^ 2 / 4 ) + 2 * C * (N / 2)

f(N) = C * ( N ^ 2 / 4 ) + C * N

f(N) = C * 1/4 * N ^ 2 + C * N
O(N²)
for (i = 0; i < n-1; i++) 
{
    small = i;
    for (j = i+1; j < n; j++)
        if (A[j] < A[small])
            small = j;
    temp = A[small];
    A[small] = A[i];
    A[i] = temp;
}
(1) for (j = 0; j < n; j++)
(2)   A[i][j] = 0;
(2) for (i = 0; i < n; i++)
(3)     for (j = 0; j < n; j++)
(4)         A[i][j] = 0;