[英]What is the time complexity of an iteration through all possible sequences of an array
一种算法,遍历数组中所有可能的索引序列。
单个循环的时间复杂度是线性的,两个嵌套循环是二次O(n ^ 2)。 但是,如果另一个循环嵌套并通过这两个索引之间分隔的所有索引怎么办? 时间复杂度是否升至立方O(n ^ 3)? 当N变得非常大时,似乎没有足够的迭代来考虑复杂性立方体,但似乎很大的是二次O(n ^ 2)
这是考虑N =数组长度的算法
for(int i=0; i < N; i++)
{
for(int j=i; j < N; j++)
{
for(int start=i; start <= j; start++)
{
//statement
}
}
}
这是N = 7时迭代的简单视觉(直到i = 7):
等等..
我们是否应该将时间复杂度视为二次,三次或不同的尺寸复杂度?
对于基本的
for (int i = 0; i < N; i++) {
for (int j = i; j < N; j++) {
// something
}
}
我们执行something
n * (n+1) / 2
倍=> O(n^2)
至于原因:它是简化形式
sum (sum 1 from y=x to n) from x=1 to n
。
对于您的新案例,我们有一个类似的公式:
sum (sum (sum 1 from z=x to y) from y=x to n) from x=1 to n
。 结果是n * (n + 1) * (n + 2) / 6
=> O(n^3)
=>时间复杂度是立方的 。
两个公式中的1
是您输入something
的成本的地方。 特别是在进一步扩展公式的地方。
请注意,所有指数可能会被一个关闭,我没有特别注意<
vs <=
等。
简答案, O(choose(N+k, N))
与O(choose(N+k, k))
相同O(choose(N+k, k))
。
这是如何到达那里的长期答案。
您的基本问题版本正确。 使用k
嵌套循环,当N
变为无穷大时,您的复杂性将为O(N^k)
。 然而,由于k
和N
都变化,行为更复杂。
让我们考虑相反的极端。 假设N
是固定的,并且k
变化。 如果N
为0,则你的时间是恒定的,因为最外层的循环在第一次迭代时失败。如果N = 1
那么你的时间是O(k)
因为你只需要一个选择就可以完成所有嵌套级别而且只有一个每次选择。 如果N = 2
则会发生更有趣的事情,你会一遍又一遍地进行嵌套,需要时间O(k^N)
。 并且通常,对于固定的N
,时间是O(k^N)
,其中k
一个因子是由于遍历嵌套所花费的时间,并且O(k^(N-1))
取决于序列前进的位置。 这是意想不到的对称性!
现在如果k
和N
都很大会发生什么? 这是什么时间复杂度? 那么这里是给你直觉的东西。
我们可以描述我们到达最里面循环的所有时间吗? 是! 考虑k+N-1
个时隙,其中k
为“进入另一个循环” ,其中N-1
为“我们将索引提前1”。 我断言如下:
1 < N
我们实际上还需要一个在独特工作中才能达到目的。 现在这看起来像一团糟,但有一个技巧可以非常意外地简化它。
诀窍是这个。 假设我们采用了其中一种模式,并在最后一段“最后输入一个循环”条目的某个地方插入了一个额外的“我们将索引提前1” 。 有多少种方法可以做到这一点? 答案是我们可以在最后一段中的任意两个点之间插入最后一个条目,包括开头和结尾,并且还有一种方法可以比条目更多。 换句话说,执行此操作的方式的数量与此迭代的独特工作量相匹配!
这意味着总工作与O(choose(N+k, N))
成正比, O(choose(N+k, N))
也是O(choose(N+k, k))
。
值得知道的是,从二项式公式的正态近似,如果N = k
则结果为O(2^(N+k)/sqrt(N+k))
,其确实比多项式增长得快。 如果您需要更一般或更精确的近似,可以使用Stirling的近似值来choose(N+k, N) = (N+k)! / ( N! k! )
choose(N+k, N) = (N+k)! / ( N! k! )
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.