简体   繁体   English

大O符号-增长率

[英]Big O Notation - Growth Rate

I am trying to understand if my reasoning is correct: 我想了解我的推理是否正确:

If I am given the following snippet of code and asked to find it's Big O: 如果我得到以下代码片段,并被要求查找它是Big O:

 for(int i = 3; i < 1000; i++)
    sum++;

I want to say O(n) because we are dealing with one for loop and sum++ which is iterated say n times but then looking at this I realise we are not dealing with n at all as we are given the amount of times this for loop iterates... but in my mind it would be wrong to say that this has a Big O of O(1) because the growth is linear and not constant and depends on the size of this loop (although the loop is 'constant'). 我想说O(n)是因为我们正在处理一个for循环,并且sum ++被迭代了n次,但是看着这个我意识到我们根本不处理n,因为我们得到了这个for循环的次数迭代...但是我认为这有一个O(1)的大O是错误的,因为增长是线性的并且不是恒定的,并且取决于此循环的大小(尽管循环是“恒定的”) 。 Would I be correct in saying that this is O(n)? 我说这是O(n)正确吗?

Also, another one that has me thinking around which has a similar setup: 另外,另一个让我思考的问题也有类似的设置:

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

Now here again I know that when dealing with a nested loop containing and outer and inner loop we would use the multiplication rule to derive our Big O. Let's assume that the inner loop was in fact j < n then I would say that the Big O of this snippet of code is O(n^4) but as it isn't and we have a the second loop running its iterations off i and not n then would it be correct to say this as a Big Order of O(n^3)? 现在我再次知道,当处理包含内部和外部循环以及内部循环的嵌套循环时,我们将使用乘法规则来得出我们的BigO。让我们假设内部循环实际上是j <n,那么我会说Big O这段代码的代码是O(n ^ 4),但不是,我们有第二个循环在i而不是n上运行其迭代,那么将其称为O(n ^的大阶数)是正确的3)?

I think what is throwing me is where 'n' is not appearing and we're given a constant or another variable and all of a sudden I'm assuming n must not be considered for that section of code. 我认为让我感到困惑的是,没有出现“ n”的地方,并且给了我们一个常量或另一个变量,突然间,我假设那部分代码中不应考虑n。 However, having said that the other part of my reasoning is telling me that despite not seeing an 'n' I should still treat the code as though there were an n as the growth rate would be the same regardless of the variable? 但是,说完我的推理的另一部分是告诉我,尽管没有看到'n',但无论变量如何,增长率都一样,我还是应该将代码视为存在n呢?

It works best if you consider the code to always be within a function, where the function's arguments are used to calculate complexity. 如果您认为代码始终位于函数内,则该函数最好用函数的参数来计算复杂度。 Thus: 从而:

// this is O(1), since it always takes the same time
void doSomething() {
    for(int i = 3; i < 1000; i++)
        sum++;
}

And

// this is O(n^6), since it only takes one argument
// and if you plot it, the curve matches t = k * n^6
void doSomethingElse(int n) {
  for(int i = 0; i < n * n * n; i++)
     for(int j = 0; j < i; j++)
        sum++;
}

In the end, the whole point of big-O is to say what the run-times (or memory-footprints; but if you don't say anything, you are referring to run-times) look like as the problem size increases . 最后,big-O的全部要点是要说明随着问题规模的增大 ,运行时间 (或内存占用量;但是如果您什么也没说,您是指运行时间)的样子 It matters not what happens in the inside (although you can use that to estimate complexity) - what really matters is what you would measure outside. 无关紧要的是内部发生了什么(尽管您可以使用它来估计复杂性)-真正重要的是您将在外部进行度量。

Looking closer at your second snippet, it's O(n^6) because: 仔细查看您的第二个片段,它是O(n ^ 6),因为:

  • outer loop runs exactly n^3 times; 外循环正好运行n ^ 3次; inner loop runs, on average, n^3 / 2 times. 内部循环平均运行n ^ 3/2次。
  • therefore, inner sum runs n^3 * k * n^3 times (with ka constant). 因此,内部和运行n ^ 3 * k * n ^ 3次(ka常数)。 In big-O notation, that's O(n^6). 用big-O表示法是O(n ^ 6)。

The first is either O(1) or simply a wrong question, just like you understand it. 首先是O(1)或仅仅是一个错误的问题,就像您理解它一样。

The second is O(n 6 ) . 第二个是O(n 6 Try to imagine the size of the inner loop. 尝试想象内部循环的大小。 On first iteration, it will be 1. On the second, 2. On the i th, it will be i , and on the last, it will be n*n*n . 在第一次迭代中,它将是1。在第二次迭代中,将是2。在第i个迭代中,它将是i ,而在最后一次迭代中,它将是n * n * n So it will be n*n*n/2 , but that's O(n*n*n) . 因此它将是n * n * n / 2 ,但这是O(n * n * n) That, times the outer O(n 3 ) is O(n 6 ) overall. 即,外部O(n 3 )的总次数O(n 6

Although the calculation of O() for your question, by others, may be correct, here is a little more insight that should help delineate the conceptual outlook for this whole asymptotic analysis story. 尽管其他人对您的问题的O()的计算可能是正确的,但这里有一些更多的见识可以帮助您描述整个渐近分析故事的概念前景。

I think what is throwing me is where 'n' is not appearing and we're given a constant or another variable and all of a sudden I'm assuming n must not be considered for that section of code. 我认为让我感到困惑的是,没有出现“ n”的地方,并且给了我们一个常量或另一个变量,突然间,我假设那部分代码中不应考虑n。

The simplest way to understand this one is to identify if the execution of a line of code is affected by/related to the current value of n. 理解这一点的最简单方法是确定一行代码的执行是否受n的当前值影响/与之相关。 Had the inner loop been, let's say, j < 10 instead of j < i, the complexity would have well been O(n^3). 假设内部循环是j <10而不是j <i,那么复杂度应该是O(n ^ 3)。

Why is any constant considered O(1)? 为什么将任何常量视为O(1)?

This may agreeably sound a little counter-intuitive at first however, here is a small conceptual summary to clear the air. 乍一看,这听起来似乎有点违反直觉,但是,这里有一个小的概念摘要可以使您大开眼界。 Let us say that your first loop runs 1000 times. 假设您的第一个循环运行了1000次。 Then you set it to 10^1000 times and try to believe that hey, it doesn't take the same time anymore. 然后将其设置为10 ^ 1000次,并尝试相信,不再需要相同的时间了。 Fair enough! 很公平! Even though it may now take your computer 5 seconds more to run the same piece of code, the time complexity still remains O(1). 即使现在您的计算机可能需要5秒多的时间才能运行同一段代码,但时间复杂度仍为O(1)。 What this practically means is that you can actually calculate the time that it takes your computer to execute that piece of code and it will remain constant forever (for the same configuration). 这实际上意味着您实际上可以计算计算机执行该代码段所花费的时间,并且该时间将永远保持不变(对于相同的配置)。

Big-Oh is actually a function on the input and not the measure of the discrete value itself (time/space). Big-Oh实际上是输入函数 ,而不是离散值本身(时间/空间)的量度。

I hope that the above explanation also helps clarify why we actually ignore the constants in the O() notation. 我希望以上解释也有助于弄清楚为什么我们实际上忽略了O()表示法中的常量。

Why is this Big-Oh thing so generalized and why is it used at the first place? 为什么Big-Oh这么泛化,为什么首先使用它?

I thought of including this extra info as I myself had this question in mind when learning this topic for the first time. 我本来想包含这些额外的信息,因为我本人在初次学习该主题时就想到了这个问题。 Asymptotic time-complexity is an apriori analysis of any algorithm to understand the worst (Big-Oh) behavior (time/space) of that program regardless of the size of the input. 渐近时间复杂度是对任何算法的先验分析,以了解该程序的最坏(Big-Oh)行为(时间/空间),而不管输入的大小如何。 Eg. 例如。 Your second code can not perform worse than O(n^6). 您的第二个代码的性能不能比O(n ^ 6)差。 It is generalized because from one computer to another, only the constant changes, not Big-Oh. 之所以这样概括是因为,从一台计算机到另一台计算机,只有不断变化,而不是Big-Oh。

With more experience, you will realize that practically, you would want your algorithm's time-complexity to be as asymptotically small as possible. 有了更多的经验,您将意识到,实际上,您希望算法的时间复杂度尽可能地渐近变小。 Till a polynomial function it is fine. 直到多项式函数都可以。 But for large inputs, today's computers start coughing if you try to run an algorithm with exponential time complexity of the order O(k^n) or O(n^n), eg. 但是对于大量输入,例如,如果您尝试以O(k ^ n)或O(n ^ n)的指数时间复杂度运行算法,今天的计算机就会开始咳嗽。 The Travelling Salesman and other NP-C/H problems. 旅行商和其他NP-C / H问题。

Hope this adds to the info. 希望这会增加信息。 :) :)

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

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