Time complexity 嵌套的for循环是否自动为O(n^2)?

Time complexity 嵌套的for循环是否自动为O(n^2)?,time-complexity,Time Complexity,我最近被问到一个关于测试数独板有效性的采访问题。一个基本的答案是for循环。基本上: for(int x = 0; x != 9; ++x) for(int y = 0; y != 9; ++y) // ... 执行嵌套的for循环以检查行。再次执行此操作以检查列。对子方块再做一个,但那个更时髦,因为我们把suoku板分成子板,所以我们最终得到两个以上的嵌套循环,可能是三个或四个 后来有人问我这个代码的复杂性。坦白地说,就我而言,董事会的所有单元都被访问了整整三

我最近被问到一个关于测试数独板有效性的采访问题。一个基本的答案是
for
循环。基本上:

for(int x = 0; x != 9; ++x)    
    for(int y = 0; y != 9; ++y)
        // ...
执行嵌套的
for
循环以检查行。再次执行此操作以检查列。对子方块再做一个,但那个更时髦,因为我们把suoku板分成子板,所以我们最终得到两个以上的嵌套循环,可能是三个或四个

后来有人问我这个代码的复杂性。坦白地说,就我而言,董事会的所有单元都被访问了整整三次,所以
O(3n)
。对我来说,我们有嵌套循环的事实并不意味着此代码自动
O(n^2)
甚至O(n^循环的最高嵌套级别)
。但我怀疑这是面试官期望的答案

换句话说,这两段代码的复杂性是什么:

for(int i = 0; i != n; ++i)
    // ...
以及:


这取决于您如何定义所谓的
N

如果电路板的大小是N乘N,那么是的,复杂性是O(N^2)


但是如果你说,网格的总数是N(即,电路板id sqrt(N)-乘以sqrt(N)),那么复杂度是O(N),或者如果你注意这个常数,那么复杂度是3O(N)。

你的一般直觉是正确的。让我们澄清一下大O符号:

Big-O为算法的最坏情况(时间)复杂度提供了一个上限,与输入的大小n有关。本质上,它是衡量工作量如何随输入量的变化而变化的指标

当你说

电路板的所有单元都被访问了整整三次,所以O(3n)

您的意思是
n
(输入的大小)是电路板中的单元数,因此访问所有单元三次确实是一个O(3n)(即O(n))操作。如果是这种情况,你是对的
然而,通常在提到数独问题(或涉及网格的问题)时,n是指每行/每列(一个
nxn
board)中的单元数。在这种情况下,运行时复杂性将是O(3n²)(实际上等于O(n²))
将来,问你的面试官n是什么是完全正确的


至于标题中的问题(嵌套for循环是否自动为O(n^2)?简短的回答是否
考虑这个例子:

for(int i = 0 ; i < n ; i++) {
    for(int j = 0 ; j < n ; j * 2) {
       ... // some constant time operation
    }
}
for(int i=0;i
外部循环进行n次迭代,而内部循环进行log2(n)次迭代,因此时间复杂度为O(nlogn)


在您的示例中,在第一个示例中,您有一个for循环进行n次迭代,因此复杂性(至少)为O(n)(操作执行次数为n次)
在第二个循环中,嵌套了两个for循环,每个循环进行sqrt(n)次迭代,因此运行时的总复杂度至少为O(n)。第二个函数不自动为O(n^2),因为它包含嵌套循环。进行的操作数量仍然是相同的顺序(n),因此这两个示例具有相同的复杂性-,因为我们假设两个示例的n相同
这是回家最关键的一点。要比较两种算法的性能,必须使用相同的输入进行比较。在你的数独问题中,你可以用几种不同的方式定义
n
,你所做的方式会直接影响问题的复杂性计算——即使工作量是一样的



*注意-这与您的问题无关,但以后请避免使用
=循环内条件。在第二个示例中,如果log(n)不是整数,则循环可能永远运行,具体取决于语言和定义方式。因此,建议使用
谢谢您的回答。尽管如此,我还是忍不住觉得用两个循环作为
n^2
来限定循环内存很奇怪/愚蠢/虚伪,因为我们对内存的心理表征是一个正方形的游戏板。。。我可以使用单个循环迭代二维数组
inta[10][10]
for(inti=0;I!=100;++I){a[I/10][I%10];}
。这是否突然使我的算法从
O(n^2)
变为
O(n)
?我也在做同样的工作!同样,这只取决于您如何定义输入n。当你考虑使用Big-O的动机时,它变得更清晰:当我们看一个编码问题和它的一些解决方案时,我们想知道我们的解决时间对于更大的输入增加的速率。换句话说,它是如何扩展的。在你的例子中,如果你定义n=10^2,你可以说你的算法是O(n),但它与定义n为10并称之为O(n^2)有什么不同?对于常见问题,n以一种特定的方式定义为一种惯例,以使讨论更容易、更有成效。
for(int i = 0 ; i < n ; i++) {
    for(int j = 0 ; j < n ; j * 2) {
       ... // some constant time operation
    }
}