Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
Algorithm 这两个嵌套循环真的具有相同的二次时间复杂度吗?_Algorithm_Time Complexity - Fatal编程技术网

Algorithm 这两个嵌套循环真的具有相同的二次时间复杂度吗?

Algorithm 这两个嵌套循环真的具有相同的二次时间复杂度吗?,algorithm,time-complexity,Algorithm,Time Complexity,下面是我提出的算法的一部分: for (int i = 0; i < n - 1; i++) for (int j = i; j < n; j++) (...) 这就是我困惑的地方: for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) (...) for(int i=0;in,f(x)

下面是我提出的算法的一部分:

for (int i = 0; i < n - 1; i++)
   for (int j = i; j < n; j++)
      (...)
这就是我困惑的地方:

for (int i = 0; i < n; i++)
   for (int j = 0; j < n; j++)
      (...)
for(int i=0;i
第二个“双循环”的复杂度也为
O(n²)
,而在最坏的情况下,它显然比第一个好得多

我错过了什么?信息准确吗?有人能解释这种“现象”吗?

恒定因素

Big-O表示法忽略常量因子,因此即使第二个循环慢一个常量因子,它们也会以相同的时间复杂度结束

它告诉您可以选择任何旧的常数因子:

。。。当且仅当存在一个正常数M

这是因为我们想分析一个算法的增长率——常数因素只会使事情变得复杂,并且往往依赖于系统(操作在不同的机器上可能会因持续时间而异)

您可以只计算某些类型的操作,但问题是选择哪种操作,如果该操作在某些算法中不占主导地位怎么办。然后,您需要将操作彼此关联起来(以系统独立的方式,这可能是不可能的),或者您可以只为每个操作分配相同的权重,但这将是相当不准确的,因为某些操作将比其他操作花费更长的时间

O(15n²+568n+8logn+23sqrt(n)+17)
(例如)真的有多有用?而不仅仅是
O(n²)


(出于以下目的,假设
n>=2

注意,我们这里实际上有渐近更小的项(即,当我们接近无穷大时更小),但我们总是可以将其简化为常数因子的问题。()

n(n+1)/2=n²/2+n/2
和
n²/2

在典型用法中,不使用O表示法的形式定义 直接的;相反,函数f的O表示法是由 以下简化规则:
如果f(x)是几个项的和,则 保留增长率最大的一个,忽略所有其他


Big-O仅用于给出渐近行为——一个比另一个快一点——它们都是O(N^2)

你也可以说第一个循环是O(N(N-1)/2。big-O的奇特数学定义如下:

如果存在常数c,n使得对于某些c和所有x>n,f(x) 这是一种奇特的说法,表示g是经过某个点的上界,应用了某个常数。然后得出O(n(n-1)/2)=O((n^2-n)/2)是O(n^2)中的大O,这对于快速分析更为整洁

(n(n-1))/2
简化为
n²/2-n/2
。如果对
n
使用非常大的数字,
n/2
的增长率将与
相比相形见绌,因此为了计算Big-O复杂性,您实际上忽略了它。同样,1/2的“常量”值不会随着
n
的增加而增加,因此您也会忽略这一点。这就给你留下了

请记住,复杂性计算与“速度”不同。一种算法的速度可能比另一种算法慢五千倍,并且仍然具有较小的Big-O复杂度。但是当你把
n
增加到非常大的数字时,一般的模式就会出现,通常可以用简单的公式来分类:
1
logn
n
,等等

有时,创建一个图形并查看显示的线类型会有所帮助:


尽管这两个图形的缩放因子非常不同,但您可以看到它生成的曲线类型几乎完全相同。

AFAIK,您的第二个代码片段

for(int i = 0; i < n; i++) <-- this loop goes for n times
     for(int j = 0; j < n; j++) <-- loop also goes for n times
          (...)

参见相关问题。@Paul I可以简化为常数因子的差。渐近
n²-n<2n²
。所以基本上,我没有理由在第二个
n^2
算法上使用第一个
n^2-n/2
算法?(因为它们是渐近相同的)@Werner:我在我的答案中添加了更多的信息。虽然这两个数字是渐近相同的,但这并不意味着速度上没有差异:这只是意味着当你得到更大的数字时,速度上的差异就不那么重要了:比如说第一个需要1000000秒才能运行,第二个只需要499500秒。第二种算法的速度是原来的两倍,但是有多少人愿意等5天让程序运行,谁不愿意等10天呢?要知道在实践中使用哪种算法,你需要比大O数更多的信息。我不得不说,如果有选择,没有人会等待x次,而他们只能等待~x/2次。。。所以big-O在帮助我决定使用这两种算法中的哪一种时不是一个有用的数字?它只适用于“彻底”不同操作系统(O(n)vs O(n^2))的算法,例如…?@Werner:我不在乎是否需要等待10微秒而不是5微秒来获得我需要的信息。这两种选择都足够快。同样,等待5天也太长了,即使备选方案是等待10天。(十秒钟对我来说通常太长了!)Big-O很有用,因为它有助于识别在更重要的大型数据集上渐近更快的算法。如果没有Big-O差异,一个算法可能仍然快得多,但这不太可能重要:要么给我找到在@Werner中运行的东西:所以在这种情况下,Big-O只在它告诉你如果N变得非常高,这两个算法都会非常慢的情况下才有用。如果您想知道哪一个速度更快,您很可能需要在真实数据集上测试它们。但那是真的
n(n+1)/2 = n²/2 + n/2
       and
n²/2 <= n²/2 + n/2 <= n²
for(int i = 0; i < n; i++) <-- this loop goes for n times
     for(int j = 0; j < n; j++) <-- loop also goes for n times
          (...)
O(n^2/2 - n/2) = O(n^2/2) (Ignoring the lower order n/2)
= O(1/2 * n^2)
= O(n^2) (Ignoring the constant factor 1/2)