Loops 大O-为什么这个算法是O(AxB)?

Loops 大O-为什么这个算法是O(AxB)?,loops,big-o,Loops,Big O,我不确定为什么这个代码的计算结果是OA*B void printUnorderedPairs(int[] arrayA, int[] arrayB) { for (int i= 0; i < arrayA.length; i++) { for (int j = 0; j < arrayB.length; j++) { for (int k= 0; k < 100000; k++) { System.out.println(array

我不确定为什么这个代码的计算结果是OA*B

void printUnorderedPairs(int[] arrayA, int[] arrayB) { 
  for (int i= 0; i < arrayA.length; i++) { 
    for (int j = 0; j < arrayB.length; j++) {
      for (int k=  0; k < 100000; k++) {
        System.out.println(arrayA[i] + "," + arrayB[j]); 
      }
    }
  }
}
当然,更准确地说是O1000*AB,我们会放弃1000,使其成为OAB。但如果数组A的长度为2呢?1000次迭代不是更重要吗?是不是因为我们知道最后一个循环是常数,并且它的值被显示出来,所以我们不计算它?如果我们知道所有的数组大小呢

有人能解释为什么我们不说它是OABC吗?如果我将代码设置为:

int[] arrayA = new int[20];
int[] arrayB = new int[500];
int[] arrayC = new int[100000];

void printUnorderedPairs(int[] arrayA, int[] arrayB) { 
  for (int i= 0; i < arrayA.length; i++) { 
    for (int j = 0; j < arrayB.length; j++) {
      for (int k=  0; k < arrayC.length; k++) {
        System.out.println(arrayA[i] + "," + arrayB[j]); 
      }
    }
  }
}
请注意,i和j中的for循环彼此独立,因此它们的运行时间是OA*B。k中的内循环是固定的迭代次数100000,并且也独立于两个外循环,因此我们得到了O100000*a*B。但是,由于k循环只是一个恒定的非变量惩罚,对于总体复杂性,我们仍然保留OA*B

如果将k中的内环从0写到C,那么就可以根据复杂性编写OA*B*C,这也是有效的。

请注意,i和j中的for循环彼此独立,因此它们的运行时间是OA*B。k中的内环是一个固定的迭代次数,100000,它也独立于两个外循环,所以我们得到了O100000*A*B。但是,由于k循环只是一个恒定的非变量惩罚,对于整体复杂性,我们仍然保留了OA*B

如果要在k中从0到C编写内部循环,那么就可以编写OA*B*C来考虑复杂性,这也是有效的。

一般来说,A*B不重要,只需要考虑它

如果有人知道A和B的长度总是一样的,那么有人会说它真的在^2上

任何类型的常数在顺序符号中都不重要,因为对于非常大的A/B数,常数的重要性可以忽略不计。

一般来说,A*B不重要,只需要考虑它

void printUnorderedPairs(int[] arrayA, int[] arrayB) { 
  for (int i= 0; i < arrayA.length; i++) { 
    for (int j = 0; j < arrayB.length; j++) {
      for (int k=  0; k < 100000; k++) {
        System.out.println(arrayA[i] + "," + arrayB[j]); 
      }
    }
  }
}
如果有人知道A和B的长度总是一样的,那么有人会说它真的在^2上

在顺序符号中,任何类型的常数都不重要,因为对于非常大的A/B数,常数的重要性可以忽略不计

void printUnorderedPairs(int[] arrayA, int[] arrayB) { 
  for (int i= 0; i < arrayA.length; i++) { 
    for (int j = 0; j < arrayB.length; j++) {
      for (int k=  0; k < 100000; k++) {
        System.out.println(arrayA[i] + "," + arrayB[j]); 
      }
    }
  }
}
由于arrayC具有恒定的长度,因此此代码的计算结果为OAB。当然,它的运行时间与AB*100000成正比。在这里,我们从不关心常量值,因为当变量越来越高,比如10^10000时,常量很容易被忽略

在第二段代码中,我们称其为O1,因为所有数组的长度都是恒定的,我们可以不使用任何变量计算其运行时间

由于arrayC具有恒定的长度,因此此代码的计算结果为OAB。当然,它的运行时间与AB*100000成正比。在这里,我们从不关心常量值,因为当变量越来越高,比如10^10000时,常量很容易被忽略


在第二段代码中,我们称其为O1,因为所有数组的长度都是恒定的,我们可以计算其运行时间,而无需任何变量。

如果运行时间或执行步骤数,或调用println的次数,或使用大O表示法评估的任何内容是OAB,这意味着运行时间接近与AB成线性比例,因为AB增长而无边界接近无穷大。从微积分的角度来看,它实际上是对无限的限制

大O不关心任何有限次数的迭代会发生什么。这是关于函数在自由变量接近无穷大时的极限行为。当然,对于A的小值,很可能存在一个支配执行时间的常数项。但当一个物体接近无穷大时,所有其他因素都变得无关紧要

考虑像Ax^3+Bx^2+Cn+D这样的多项式。当x增长到无穷大时,它将与x^3成正比——不管a、B、C或D的大小。B可以是所有大O的格雷厄姆数;无穷大仍然比你选择的任何大的有限数都大,因此x^3项占主导地位

所以首先,考虑一下如果A是2,那么A不是真的符合AB接近无穷大的精神

第二,记住与AB成比例意味着等于AB乘以某个常数;这个常数是多少并不重要。如果常数恰好为10000,则可以。说某物与2N成正比,等于说它与N成正比,或者说它与N的任何其他倍数成正比。因此,O2N与ON是相同的。按照惯例,当使用大O表示法删除任何常数因子时,我们总是进行简化。所以我们会一直写下去,永远不会写。出于同样的原因,我们将编写OAB而不是O10000AB

最后,我们不说OABC仅仅是因为在你的问题中,你的内部循环的迭代次数恰好是一个常数;这也恰好等于10000。这就是为什么我们说它是OAB而不是OABC,因为C不是自由变量;它的硬编码是10000。如果尺寸 B的e不应该改变,因为无论什么原因,它都是常数,那么你可以说它只是OA。但是如果你允许B无约束增长,那么限制是OAB,如果你也允许C无约束增长,那么限制是OABC。您可以根据分析的上下文来决定哪些数字是常量,哪些变量是自由变量


您可以在Wikipedia上阅读更多信息。

如果运行时间或执行步骤的数量,或者调用println的次数,或者您使用大O符号评估的是OAB,这意味着运行时间接近与AB成线性比例的AB增长,而无边界接近无穷大。从微积分的角度来看,它实际上是对无限的限制

大O不关心任何有限次数的迭代会发生什么。这是关于函数在自由变量接近无穷大时的极限行为。当然,对于A的小值,很可能存在一个支配执行时间的常数项。但当一个物体接近无穷大时,所有其他因素都变得无关紧要

考虑像Ax^3+Bx^2+Cn+D这样的多项式。当x增长到无穷大时,它将与x^3成正比——不管a、B、C或D的大小。B可以是所有大O的格雷厄姆数;无穷大仍然比你选择的任何大的有限数都大,因此x^3项占主导地位

所以首先,考虑一下如果A是2,那么A不是真的符合AB接近无穷大的精神

第二,记住与AB成比例意味着等于AB乘以某个常数;这个常数是多少并不重要。如果常数恰好为10000,则可以。说某物与2N成正比,等于说它与N成正比,或者说它与N的任何其他倍数成正比。因此,O2N与ON是相同的。按照惯例,当使用大O表示法删除任何常数因子时,我们总是进行简化。所以我们会一直写下去,永远不会写。出于同样的原因,我们将编写OAB而不是O10000AB

最后,我们不说OABC仅仅是因为在你的问题中,你的内部循环的迭代次数恰好是一个常数;这也恰好等于10000。这就是为什么我们说它是OAB而不是OABC,因为C不是自由变量;它的硬编码是10000。如果B的大小是不变的,无论什么原因,你都可以说它只是OA。但是如果你允许B无约束增长,那么限制是OAB,如果你也允许C无约束增长,那么限制是OABC。您可以根据分析的上下文来决定哪些数字是常量,哪些变量是自由变量


你可以在维基百科上阅读更多信息。

详细答案!谢谢详细回答!谢谢