简体   繁体   English

function 的大 O 符号

[英]Big-O Notation of function

The following function takes a 1D array A of size n as a parameter and returns a 2D array M of size nx n.以下 function 将大小为 n 的一维数组 A 作为参数,并返回大小为 nx n 的二维数组 M。 M stores average values. M 存储平均值。 These average values are calculated from array A between 2 iterative variables (i an j) if i <= j using the formula M[i][j]=(A[i] +...+A[j])/( j-i+1).如果 i <= j 使用公式 M[i][j]=(A[i] +...+A[j])/( j-i+1). For example if i=1, and j=3.例如,如果 i=1,且 j=3。 Then M[0][3] will store the value calculated from M[1][3] = (A[1] + A[2] + A[3])/3-1+1然后 M[0][3] 将存储从 M[1][3] = (A[1] + A[2] + A[3])/3-1+1 计算的值

 public float[][] averageArray(float[] A){
        int n = A.length;
        float sum;
        float[][] M = new float[n][n];

        for(int j = 0; j<n;j++){
            for(int i = 0; i<n; i++){

                if(i<=j) {
                    sum = 0;
                    for (int k = i; k <= j; k++) {
                        sum += A[k];

                    }
                    M[i][j] = sum / (j - i + 1);
                }else{
                    M[i][j] = 0;
                }

                System.out.println("["+ i +"]" + "["+ j +"]: "+ M[i][j]);
            }

        }
        return M;
    }

I'm confused about the big-o notation of this function. I know that the first two for loops produce a big-O of O(n^2) but because the third loop is conditional, I'm not sure how to put that into big-O notation.我对这个 function 的大 O 符号感到困惑。我知道前两个 for 循环产生 O(n^2) 的大 O 但因为第三个循环是有条件的,所以我不确定如何放置那变成大O符号。 From tests I found that the number of times the 3rd loop is executed increases with the j value (ex if j = 3 then the loop executes 3 times, if j = 5 then the loop will execute 5 times).从测试中我发现第 3 个循环执行的次数随着 j 值的增加而增加(例如,如果 j = 3 则循环执行 3 次,如果 j = 5 则循环将执行 5 次)。

tl;dr when you're not sure how it factors into the big-o runtime, create a summation for the loop, and then convert that summation into a function of n tl;dr当你不确定它如何影响 big-o 运行时时,为循环创建一个总和,然后将该总和转换为n的 function

Sometimes you'll encounter questions like "how many times did the line inside the innermost loop execute in terms of n . It's not quite the runtime analysis, but here's an analysis n.netheless. It will help you get a better picture of the big-o runtime.有时你会遇到这样的问题,比如“最内层循环中的行执行了多少次n 。它不完全是运行时分析,但这里有一个分析 n.netheless。它会帮助你更好地了解大-o 运行时间。

It might be helpful to put a counter inside the inner loop and see how many times it gets executed.在内部循环中放置一个计数器并查看它执行了多少次可能会有所帮助。

It also might be helpful to draw a grid and color the squares where i <= j and j is the row index (since it's the first loop's variable) and i is the column index).绘制网格并为正方形着色也可能会有帮助,其中i <= jj是行索引(因为它是第一个循环的变量)并且i是列索引)。 When you do this, you'll see that all the colored squares split the square grid into 2 triangles down the diagonal from top-left to bottom right.执行此操作时,您会看到所有彩色方块都将正方形网格沿对角线从左上角到右下角分成 2 个三角形。 Anything that falls directly on the line still counts (because you said <= rather than < ).任何直接落在线上的东西仍然很重要(因为你说的是<=而不是< )。 The colored squares will be the bottom/left triangle.彩色方块将是底部/左侧的三角形。

This is just a depiction of where the innermost loop will actually do something .这只是最内层循环将实际执行某些操作的位置的描述

The outer 2 loops will now iterate over each location in the grid.外面的 2 个循环现在将遍历网格中的每个位置。 We'll call this the current location .我们将其称为当前位置 A line of code in the inner loop will now execute once for each colored square above the current location in that column of the grid (and once for the current location if it's colored) each time a new location is determined by the outer 2 loops.每次由外部 2 个循环确定新位置时,内部循环中的一行代码现在将对网格该列中当前位置上方的每个彩色方块执行一次(如果当前位置是彩色的,则对当前位置执行一次)。

After visualizing this, you can more easily see how to count the number of times this will execute.将其可视化后,您可以更轻松地了解如何计算这将执行的次数。 The first column of the grid has n colored squares.网格的第一列有n 个彩色方块。 The first time this column will be counted will be when the top left square is chosen(j=0, i=0).第一次计算该列是在选择左上角的方块时(j=0,i=0)。 The second time will be when (j=1, i=0).第二次会在(j=1, i=0)的时候。 SO, let's fill in a grid where the value at each location is the number of times each cell is counted.所以,让我们填充一个网格,其中每个位置的值是每个单元格被计数的次数。 It will be like this:它将是这样的:

[n,  0 ,  0,  0, ... ]
[n-1, n-1, 0, 0, ... ]
[n-2, n-2, n-2, 0, ...]

You can see the picture now.你现在可以看到图片了。 Adding up everything in this grid will now tell you how many times your inner-most loop executed.现在将此网格中的所有内容相加将告诉您最内层循环执行了多少次。

  1. First row has 1 n第一行有 1 n
  2. Second row has 2 (n-1) 's第二行有 2 (n-1)
  3. Third row has 3 (n-2) 's第三行有 3 (n-2) 个

You can see the pattern of (nj) * (j+1) as the total for each row.您可以将 (nj) * (j+1) 的模式视为每行的总数。

Sum over the rows to get the total.对行求和以获得总数。

You end up with a sum like so:你最终得到这样的总和:

for(int i = 0; i < n; i++)
    sum += (n-i)*(i+1);
return sum;

最内层循环执行

That's just for the number of times that the inner-most loop executed.这只是最内层循环执行的次数。 Now for the times the inner-most loop did not get executed.现在,最内层的循环没有被执行。 This part is much easier.这部分要容易得多。 It's simply the number of non-colored squares in the grid from earlier.它只是之前网格中非彩色方块的数量。

Because it's an n by n grid, n 2 /2 would seem like the right answer.因为它是一个nn的网格,n 2 /2 似乎是正确的答案。 BUT the main diagonal squares are all colored.但是主对角线方块都是彩色的。 n 2 /2 already counts half of that line, so we have to take out the other half: n/2. n 2 /2 已经计算了该行的一半,所以我们必须去掉另一半:n/2。

So, the total number of executions would be the for loop sum above, plus half the square of n (non-colored squares), minus half of n (because you just added half of the diagonal that was already colored in the previous plus term).因此,执行的总数将是上面的for循环总和,加上 n 的平方的一半(无色方块),减去 n 的一半(因为你刚刚添加了在前一个项中已经着色的对角线的一半).

This ends up looking like这最终看起来像在此处输入图像描述

The meaning of the first 2 terms is the number of times that the inner-most for-loop did NOT execute.前两项的含义是最内层的 for 循环执行的次数。

When I run this code, the following is my results:当我运行此代码时,以下是我的结果:

  1. n=10 n=10
    • inner-loop executions: 220内循环执行:220
    • total executions: 265总处决:265
    • 220 + 10 2 /2 - 10/2 (220 + 50 - 5 = 265) 220 + 10 2 /2 - 10/2 (220 + 50 - 5 = 265)
  2. n=100 n=100
    • inner-loop executions: 171700内循环执行:171700
    • total executions: 176650总处决:176650
  3. n=1000 n=1000
    • inner-loop executions: 167167000内循环执行:167167000
    • total executions: 167666500总处决:167666500
  4. n=10000 n=10000
    • inner-loop executions: 166716670000内循环执行:166716670000
    • total executions: 166766665000总处决:166766665000
  5. n=100000 n=100000
    • inner-loop executions: 166671666700000内循环执行:166671666700000
    • total executions: 166676666650000总处决:166676666650000
  6. n=100000000 (did it just for the lolz, you can already see the pattern) n = 100000000(只是为了lolz,你已经可以看到模式了)
    • inner-loop executions: 166666671666666700000000内循环执行:166666671666666700000000
    • total executions: 166666676666666650000000总处决:166666676666666650000000

AND FOR MY FINAL REVEAL, SINCE YOU'VE READ THIS FAR This is an O(n 3 ) function.对于我的最后启示,既然你已经读到这里,这是一个 O(n 3 ) function。

I won't get into it too much, but the summation for the number of times that the inner-most for-loop executes simplifies down to我不会过多地讨论它,但是最内层的 for 循环执行次数的总和可以简化为在此处输入图像描述

Adding in the 2 terms that count the number of times the inner-most loop did NOT execute, group the like-terms for easier simplification and you'll end up with this:添加计算最内层循环执行次数的 2 个术语,将类似术语分组以便于简化,您将得到以下结果:

在此处输入图像描述

You can use these last 2 formulas to verify the data that I've shared above.您可以使用最后两个公式来验证我在上面分享的数据。 You can also empirically verify by adding counters into your loops and running them to see how many times they execute and compare that with the values given by these formulas(for values as large as those I provided you'll need to use BigInteger s or some other arbitrarily large number format).您还可以通过在循环中添加计数器并运行它们以查看它们执行了多少次并将其与这些公式给出的值进行比较来凭经验进行验证(对于与我提供的值一样大的值,您需要使用BigInteger s 或一些其他任意大的数字格式)。 If you don't trust me, or your computer, you can also try throwing some of this information at an online tool which solves equations, such as wolfram alpha.如果您不信任我或您的计算机,您也可以尝试将其中的一些信息丢给求解方程式的在线工具,例如 wolfram alpha。 Lastly, if this is from an exam question, you can take this to your professor and showcase the nature of this problem and the exact number of for-loop executions given n is the length of the array A .最后,如果这是来自考试问题,您可以将其带给您的教授并展示此问题的性质以及给定nfor-loop执行的确切次数是数组A的长度。 If all this is wrong, I've at the least shown that it's true for powers of 10. Hope this helps in some way.如果所有这些都是错误的,我至少已经证明它对 10 的幂是正确的。希望这在某种程度上有所帮助。

Update: Based on @loganrussell48's analysis and comment below, the conclusion I came up with of n^2 is wrong.更新:根据@loganrussell48 的分析和下面的评论,我得出的关于n^2的结论是错误的。


Wrong answer:错误的答案:

Larger factors like n^2 'eclipse' smaller factors like the one you're searching for (which we know is less than n , which is why the answer will be less than n^3 ).较大的因素,如n^2 'eclipse' 较小的因素,如您正在搜索的因素(我们知道它小于n ,这就是答案将小于n^3的原因)。

It's safe to say your big-O is larger than n^2 but smaller than n^3 .可以肯定地说你的 big-O 大于n^2但小于n^3 If you consult a list of time complexities (like https://en.wikipedia.org/wiki/Time_complexity#Table_of_common_time_complexities ) you'll see those two complexities are adjacent.如果您查阅时间复杂度列表(例如https://en.wikipedia.org/wiki/Time_complexity#Table_of_common_time_complexities ),您会发现这两个复杂度是相邻的。

Big-O is all about simplification. Big-O 就是关于简化。 Constant factors drop out.常数因子消失。 Smaller factors drop out.较小的因素会消失。 In this case, the third factor of n ( n * n * n ) is much smaller than n .在这种情况下, n的第三个因子 ( n * n * n ) 比n小得多。 The condition is met half the time and executes between i and j times (both less than n , so using estimation half of half of n).该条件满足一半的时间并在ij次之间执行(均小于n ,因此使用 n 的一半的估计一半)。 This third factor of n is now much smaller than n . n的第三个因子现在比n小得多。

Common complexities smaller than n are insignificant compared to n^2 .n^2相比,小于n的常见复杂性微不足道。

In this case, n^2 is the important thing you are trying to convey.在这种情况下, n^2是您要传达的重要信息。

常见复杂度图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM