Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 时间复杂度(大O)-当我们有2个嵌套FOR循环时,N的值能否决定时间复杂度是O(1)还是O(N)?_Performance_Optimization_Time_Computer Science - Fatal编程技术网

Performance 时间复杂度(大O)-当我们有2个嵌套FOR循环时,N的值能否决定时间复杂度是O(1)还是O(N)?

Performance 时间复杂度(大O)-当我们有2个嵌套FOR循环时,N的值能否决定时间复杂度是O(1)还是O(N)?,performance,optimization,time,computer-science,Performance,Optimization,Time,Computer Science,假设我有2个嵌套for循环和1个大小为N的数组,如下面的代码所示: int result = 0; for( int i = 0; i < N ; i++) { for( int j = i; j < N ; j++) { result = array[i] + array[j]; // just some funny operation } } int结果=0; 对于(int i=0;i

假设我有2个嵌套for循环和1个大小为N的数组,如下面的代码所示:

int result = 0;

for( int i = 0; i < N ; i++)
{
    for( int j = i; j < N ; j++)
    {
        result = array[i] + array[j]; // just some funny operation
    }
}
int结果=0;
对于(int i=0;i
以下是两个案例:

(1) 如果严格来说,约束条件是N>=1000000,那么我们可以肯定地说时间复杂度是O(N^2)。我们都知道这是事实

(2) 现在,如果约束条件是N<25,那么人们可能会说,因为我们知道N总是太小,时间复杂度估计为O(1),因为用现代计算机运行和完成这两个for循环所需的时间很短?听起来对吗

请告诉我N的值是否在决定时间复杂度O(N)的结果中起作用?如果是,那么N值需要多大才能发挥作用(1000?5000?20000?500000?),换句话说,这里的一般经验法则是什么



有趣的理论问题:如果15年后,计算机速度如此之快,即使N=25000000,这两个for循环也可以在1秒内完成。在那个时候,我们可以说即使对于N=25000000,时间复杂度也是O(1)吗?我想当时的答案是肯定的。你同意吗?

tl:dr No.N的值对时间复杂度没有影响。O(1)与O(N)是关于“全部N”或当N增加时计算量如何增加的陈述

好问题!这让我想起了我第一次尝试理解时间复杂性的时候。我想很多人都必须经历类似的过程才能开始有意义,所以我希望这次讨论能帮助其他人

首先,您的“有趣操作”实际上比您想象的更有趣,因为您的整个嵌套for循环可以替换为:

result = array[N - 1] + array[N - 1]; // just some hilarious operation hahaha ha ha
由于每次都会覆盖
result
,因此只有最后一次迭代才会影响结果。我们将回到这个话题

就您在这里真正要问的问题而言,Big-O的目的是提供一种有意义的方法,以一种与输入大小无关、与计算机处理速度无关的方式来比较算法。换句话说,O(1)和O(N)与N的大小无关,也与计算机的“现代化”程度无关。所有这些都会影响算法在具有特定输入的特定机器上的执行时间,但不会影响时间复杂度,即O(1)与O(N)

这实际上是一个关于算法本身的声明,因此数学讨论是不可避免的,正如dxiv在他的评论中优雅地暗示的那样。免责声明:我将省略数学中的某些细微差别,因为关键的东西已经有很多要解释了,我将遵从网络和教科书上其他地方堆积如山的完整解释

你的代码是一个很好的例子,可以理解Big-O告诉我们什么。你写它的方式,它的复杂性是O(N^2)。这意味着,无论你在哪台机器上运行你的代码,或者你在哪个时代运行你的代码,如果你要计算计算机对每N所做的操作的数量,并把它作为一个函数,比如f(N),存在一些二次函数,比如g(N)=9999N^2+9999N+999,对于所有N,它都大于f(N)

但是等一下,如果我们只需要找到足够大的系数,以使g(N)成为上界,我们难道不能声称算法是O(N)并找到一些g(N)=an+b,其系数足够大,以致于它是f(N)的上界吗这个问题的答案是你需要理解的最重要的数学观察,才能真正理解大O符号。剧透答案是否定的

对于视觉效果,请在Desmos上尝试此图表,您可以在其中调整系数:[https://www.desmos.com/calculator/3ppk6shwem][1]

无论您选择什么系数,形式为a^2+bN+c的函数最终将超过形式为a+b的函数(两者都具有正a)。你可以像g(N)=9999n+99999那样把一条线推到你想要的高度,但即使是函数f(N)=0.01N^2+0.01N+0.01也会穿过这条线,并在N=999900后增长超过它。没有一个线性函数是二次函数的上界。类似地,没有常数函数是线性函数或二次函数的上界。然而,我们可以找到这个f(N)的二次上界,比如h(N)=0.01N^2+0.01N+0.02,所以f(N)在O(N^2)中。这一观察结果使我们可以直接说出O(1)和O(N^2),而不必区分O(1)、O(3)、O(999)、O(4N+3)、O(23N+2)、O(34N^2+4+e^N)等。通过使用诸如“存在一个函数”,我们可以刷除地毯下的所有常数系数

所以有一个二次上界,也就是O(N^2),意味着函数f(N)不大于二次函数,在这种情况下正好是二次函数。这听起来就像是比较多项式的阶数,为什么不说这个算法是2阶算法呢?为什么我们需要这个超抽象的“存在一个上界函数,使得blablabla…”?这是Big-O解释非多项式函数所必需的推广,一些常见的函数是logN、NlogN和e^N

例如,如果您的算法所需的操作数由f(N)=floor(50+50*sin(N))给出,我们会说它是O(1),因为存在一个常数函数,例如g(N)=101,它是f(N)的上界。在本例中,您有一些执行时间振荡的奇怪算法,但您可以通过简单地说它是O(1),向其他人传达它对于大输入不会减慢多少速度。整洁的另外,我们有一种方式有意义地说,这个算法与三角函数