计算Big-O复杂性



我最终会给这个程序一个大约有60000个400像素图像的输入文件,所以我试图了解这个代码如何在大输入的情况下运行。为了可读性,我用"blah"替换了不重要的内容,并用简单的字母(nnmmkk)替换了所有ArrayList名称。

        for (Perceptron P : nn){
            //blah
        }
        for (Perceptron P : mm) {
            //blah
        }
        for (Perceptron P : kk){
            //blah
        }
        for (Perceptron P : mm) {
            for (int i = 0; i < nn; i++) {
                //blah
            }
            for (int j = 0; j < kk; j++){
                //blah
            }
        }
        for (Perceptron X : nn){
            for (Perceptron Y : mm){
                //blah
            }
        }
        for (Perceptron Z : kk){
            for (Perceptron Y : mm){
                //blah
            }
        }

我认为答案是O(nn+mm+kk+mm(nn+kk)+nnmm+kkmm)。如果我知道nn是400,mm是300,kk是10,那么这就是O(246710)。但现在我被卡住了。我真的不知道O(246710)是什么意思。我必须一次只计算其中一个变量的big-O吗?如果是这样,那有什么好处?我只是想知道这会如何表现。感谢

Big-O只涉及运行时间中最大的项,在这种情况下是O(mm*(nn+kk))。生成这个术语的代码部分是以下嵌套循环:

for (Perceptron P : mm) {
    for (int i = 0; i < nn; i++) {
        //blah
    }
    for (int j = 0; j < kk; j++){
        //blah
    }
}

如果您向我们揭示kkmmnn与图像的实际大小之间的关系,那么我们可以用更有意义的术语给您一个运行时间的界限。

O(N)意味着程序的执行时间与N成线性比例。因此,O(246710)实际上并不意味着什么。

程序的复杂性实际上是O(mm*(nn+kk))。这并不能告诉你特定大小的输入需要多长时间(为此,你需要知道所有单独的操作需要多长时间),只是如果mm的大小翻倍,而所有其他条件保持不变,那么你的程序执行时间大约是以前的两倍。

Big O并没有按照你想象的方式使用。它用于确定最坏的情况。现在,如果nnmmkk在数据存储中都是线性的,并且是非嵌套的,那么它就是简单的O('the-largest-chain')。现在我们还不知道nnmmkk之间的关系,所以我能告诉你的最好的是;因为你永远不会把它们和自己嵌套在一起,所以它是线性的。

两个快速的例子来展示它的作用。

输入:

int[] arr = {1,2,3}

示例#1

for (int i : arr) {
    // do something
}

在这种情况下,Big-O只是O(n),因为您只从数组的开始到结束进行迭代,它与元素成正比。

示例#2

for (int i : arr) {
    for (int j : arr) {
        // do something
    }
}

现在输入和算法之间的关系是二次的,给出O(n2)

我建议在这里读一读,或者遵循教程,因为它可以澄清比我的答案多得多的东西。

在您的情况下,您从未嵌套输入,并且由于变量之间没有直接关系,因此Big-O将只是将它们相加。在你的情况下应该是O(mm(nn+kk))

Big-O表示法以输入大小表示时间,此时大小变为无穷大。

首先,您必须决定输入变量。在您的示例中,nn、mm和kk是输入变量。

然后我们计算我们需要进行多少次迭代:

nn + mm + kk + mm(nn + kk) + nn + kk

简化:

2nn + 2kk + mm(nn + kk + 1)

我们有3个项,但当所有项都进入无穷大时,只有具有最高渐近增长阶的项才有意义,它是mm(nn+kk+1)。你真的应该检查渐近阶,因为在这个答案中解释它太长了。

我们将mm(nn+kk+1)简化为毫米(nn+kk)

现在我们有mm(nn+kk),在这里我们在nnkk中选择生长更快的一个,如何知道哪个生长更快?这取决于你的投入。假设我们选择nn,那么我们有O(mm*nn)。属于O(n^2)类别。

通过对算法的运行时间分析,您有最坏情况平均情况最佳情况序比处理器的速度更重要。这与算法执行的操作数有关。(也称为n

以下是使用Big-O-符号的几个例子:

线性:60n + 5或O(n)。这意味着它需要n次操作,你的普通循环

二次型:2n^2 + 2n或O(n^2)。这在嵌套循环中很常见

对数:number of digits in n或O(1)。这在Dictionaries中使用,并且将在很少的操作后访问元素。(请尝试并记住在适用的情况下应用此选项以提高性能。)

假设所有输入大小都向无穷大移动,则大O表示法应简化为算法的最大最坏情况分母。

所以你的表达式O(nn+mm+kk+mm(nn+kk)+nnmm+kkmm)应该被简化为O(mmnn+mmkk)。

我认为你对复杂性O(nn+mm+kk+mm(nn+kk)+nnmm+kkmm)的精确表达式是正确的。它测量变量的复杂性变化,所以不要用值代替变量,在你的情况下,当nn=400,mm=300,kk=10时,它可以简化为O(nnmm)或O(nnnn)

最新更新