我的印象是,为了找到嵌套for循环的大O,将每个forloop的大O与下一个for循环进行多重组合。大O会不会:
for i in range(n):
for j in range(5):
print(i*j)
是O(5n)?如果是这样,大O会:
for i in range(12345):
for j in range(i**i**i)
for y in range (j*i):
print(i,j,y)
是O(12345*(i**i**i)*(j*i)
?或者它是O(n^3)
因为它嵌套3次?
我很困惑
答案 0 :(得分:4)
这有点简化,但希望能够理解Big-O的含义:
Big-O是关于“我的代码执行了多少次?”的问题,在代数中回答它,然后问“从长远来看哪个术语最重要?”
对于您的第一个示例 - 调用print
语句的次数是5n
次。外循环中n
次在内循环中的时间5
次。从长远来看,最重要的是什么?从长远来看,只有n
很重要,因为5
的值永远不会改变!因此整体Big-O复杂度为O(n)
。
对于您的第二个示例 - 调用print语句的次数非常大,但是不变。外循环运行12345
次,内循环运行一次,然后16
次,然后7625597484987
...一直运行到12345^12345^12345
。最里面的循环以类似的方式上升。我们注意到所有这些都是常数!调用print语句的次数实际上并未完全改变 。当算法在常量时间中运行时,我们将其表示为O(1)
。从概念上讲,这与上面的示例类似 - 就像5n / 5 == n
,12345 / 12345 == 1
。
你选择的两个例子只涉及剥离常数因素(我们总是在Big-O中做,它们永远不会改变!)。另一个例子是:
def more_terms(n):
for i in range(n):
for j in range(n):
print(n)
print(n)
for k in range(n):
print(n)
print(n)
print(n)
对于此示例,print语句称为2n^2 + 3n
次。对于第一组循环,外循环为n
次,内循环为n
次,内循环内为2
次。对于第二组,循环n
次,每次迭代3
次。首先我们删除常量,离开n^2 + n
,现在重要的是什么?当n
为1
时,两者都不重要。但是n
越大,差异越大,n^2
的增长速度比n
快得多 - 因此此函数的复杂度为O(n^2)
。
答案 1 :(得分:0)
对于第二个例子,你是正确的O(n ^ 3)。你可以像这样计算大O:
任意数量的嵌套循环都会增加1到n的额外功率。所以,如果我们有三个嵌套循环,那么大O就是O(n ^ 3)。对于任意数量的循环,大O是O(n ^(循环数))。一个循环就是O(n)。任何n的单项式,例如O(5n),都只是O(n)。
答案 2 :(得分:0)
你误解了O(n)的含义。一开始很难理解,所以不理解它就不会感到羞耻。
O(n)的意思是“这个增长速度和n一样快”。它有一个严格的数学定义,但它基本上归结为这个。
如果f和g都是函数,f = O(g)意味着你可以选择一些常数C,并在像n这样的大输入上,f(n)< C * g(n)。“大O代表一个上限,它不关心常数因子,所以如果f = O(5n),那么f = O(n)。