Big o 算法的运行时间与实际情况不符

Big o 算法的运行时间与实际情况不符,big-o,Big O,我有以下算法: 我对该算法进行了如下分析: 因为外部for循环从i到n,它最多迭代n次, j上的循环再次从i到n迭代,我们最多可以说n次, 如果我们对整个算法执行相同的操作,我们将有4个嵌套for循环,因此运行时间将为O(n^4) 但当我为不同的输入大小运行此代码时,我得到以下结果: 如你所见,结果更接近n^3?有人能解释为什么会发生这种情况,或者我的分析有什么错,我得到了一个宽松的界限吗?我确信有一个概念上的方法来解释为什么,但是你可以通过归纳证明上面有(n+2)*(n+1)*n*(n-1

我有以下算法:

我对该算法进行了如下分析:

因为外部for循环从i到n,它最多迭代n次, j上的循环再次从i到n迭代,我们最多可以说n次, 如果我们对整个算法执行相同的操作,我们将有4个嵌套for循环,因此运行时间将为O(n^4)

但当我为不同的输入大小运行此代码时,我得到以下结果:


如你所见,结果更接近n^3?有人能解释为什么会发生这种情况,或者我的分析有什么错,我得到了一个宽松的界限吗?

我确信有一个概念上的方法来解释为什么,但是你可以通过归纳证明上面有
(n+2)*(n+1)*n*(n-1)/24个
循环。把证据留给读者

换句话说,它确实是
O(n^4)

编辑:您的计数增加太频繁。只需尝试以下代码来计算循环数:

    for (int n = 0; n < 30; n++) {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                for(int k = 0; k < j; k++) {
                    for (int h = k; h < i; h++) {
                        sum++;
                    }
                }
            }
        }
        System.out.println(n + ": " + sum + " = " + (n + 2) * (n + 1) * n * (n - 1) / 24);
    }
for(int n=0;n<30;n++){
整数和=0;
对于(int i=0;i
我相信有一种概念上的方法来解释原因,但你可以通过归纳证明上面有
(n+2)*(n+1)*n*(n-1)/24个循环。把证据留给读者

换句话说,它确实是
O(n^4)

编辑:您的计数增加太频繁。只需尝试以下代码来计算循环数:

    for (int n = 0; n < 30; n++) {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                for(int k = 0; k < j; k++) {
                    for (int h = k; h < i; h++) {
                        sum++;
                    }
                }
            }
        }
        System.out.println(n + ": " + sum + " = " + (n + 2) * (n + 1) * n * (n - 1) / 24);
    }
for(int n=0;n<30;n++){
整数和=0;
对于(int i=0;i
正式地说,您可以使用Sigma表示法,按照以下步骤获得算法的复杂度增长顺序:

此外,得到的方程式告诉我们在最内层循环中执行的迭代的确切次数:

int sum = 0;
for( i=0 ; i<n ; i++ )
    for( j=i ; j<n ; j++ )
        for( k=0 ; k<j ; k++ )
            for( h=0 ; h<i ; h++ )
                sum ++; 
printf("\nsum = %d", sum);
int和=0;

对于(i=0;i形式上,您可以使用Sigma表示法,按照以下步骤获得算法的增长复杂度顺序:

此外,得到的方程式告诉我们在最内层循环中执行的迭代的确切次数:

int sum = 0;
for( i=0 ; i<n ; i++ )
    for( j=i ; j<n ; j++ )
        for( k=0 ; k<j ; k++ )
            for( h=0 ; h<i ; h++ )
                sum ++; 
printf("\nsum = %d", sum);
int和=0;

对于(i=0;i你有一个相当复杂的算法。运算的数量明显小于n^4,但它比n^4少多少,以及它是否为O(n^3)并不明显

检查n=1到9的值并根据结果进行猜测是毫无意义的


为了得到一个稍微好一点的想法,假设步骤的数量是c*n^3或d*n^4,并为1制作一个值c和d的表格您有一个相当复杂的算法。操作的数量明显少于n^4,但它比n^4少多少,以及是否为O(n^3)都不明显

检查n=1到9的值并根据结果进行猜测是毫无意义的


为了得到一个稍微好一点的想法,假设步数是c*n^3或d*n^4,并为1的值c和d制作一个表,它是
O(n^4)
你只需要看足够大的n。对于小的
n
来说,低阶项相对较大,因此它们占主导地位。
O(n^4)
最终会通过。我认为查看计数器值不足以判断此算法花费了多少时间。我真的无法理解为什么要使用计数作为计算运行时间的因子。它只是一个变量,其值将取决于for循环。显然,在这里,for循环中扭曲值将增加e计数器值。更多的O(n^4)表示最坏的情况,你没有利用yetIt的
O(n^4)
你只需要看足够大的n。低阶项对于小的
n
相对较大,所以它们占主导地位
最终会通过。我认为查看计数器值不足以判断此算法花费了多少时间。我真的无法理解为什么要使用计数作为计算运行时间的因子。它只是一个变量,其值将取决于for循环。显然,在这里,for循环中扭曲值将增加e计数器值。更多的O(n^4)意味着最坏的情况,你没有利用yetThanks来回答,那么如果我想用θ来表示运行时间呢?如果我没有用这个代码进行观察,我会说它是渐近θ(n^4),但现在我有疑问。我们能说它是θ(n^4)吗?是的。我给了你公式。它是θ((n+2)(n+1)n(n-1)/24)。非常感谢,我观察了你的公式,但是你可以从上面的结果中看到,对于输入大小3,我得到19作为运行时间,但是这个公式给出了5。问题在哪里?感谢你的回答,那么如果我想说运行时间θ呢?如果我没有使用该代码进行观察,我会说它是渐近θ(n^4)但现在我有点怀疑。我们能说它是θ(n^4)吗?是的。我给了你公式。它是θ((n+2)(n+1)n(n-1)/24)。非常感谢,我观察了你的公式,但正如你从上面的结果中所看到的,我得到19作为输入大小3的运行时间,但这个公式给出了5。问题出在哪里?h从k到I变化,而不是从0到I,因此结果会小得多。h从k到I变化,而不是从0到I,因此结果会小得多。