让我们看一下代码,看看递归应该是什么。
首先,让我们看一下循环:
for i=1 to n
{
for j=i to 2i
{
for k=j-i to j-i+100
write (i, j, k);
}
}
这做了多少工作?好吧,让我们从简化它开始。与其让j 从i 计数到2i,不如定义一个从0 计数到i 的新变量j'。这意味着j' = j - i,所以我们得到这个:
for i=1 to n
{
for j' = 0 to i
{
for k=j' to j'+100
write (i, j' + i, k);
}
}
啊,好多了!现在,让我们也将k 重写为k',其中k' 的范围从1 到100:
for i=1 to n
{
for j' = 0 to i
{
for k'= 1 to 100
write (i, j' + i, k' + j);
}
}
由此更容易看出这个循环的时间复杂度为 Θ(n2),因为最里面的循环做了 O(1) 的工作,而中间的循环将运行 1 + 2 + 3 + 4 + ... + n = Θ(n2) 次。请注意,它不完全是 100n2,因为总和不完全是 n2,但它很接近。
现在,让我们看看递归部分:
for i=1 to 7
Alg(n-2);
对于初学者来说,这简直是愚蠢的!你没有理由想要做这样的事情。但是,话虽如此,我们可以说这是对大小为 n - 2 的输入的 7 次算法调用。
据此,我们得到这个递归关系:
T(n) = 7T(n - 2) + Θ(n2) [如果 n ≥ 3]
T(n) = Θ(1) [否则]
现在我们有了递归,我们可以开始计算时间复杂度。这最终有点棘手。如果您考虑一下我们最终会做多少工作,我们会做到的
- 有 1 个大小为 n 的调用。
- 有 7 个大小为 n - 2 的调用。
- 有 49 个大小为 n - 4 的调用。
- 有 343 个大小为 n - 6 的调用。
- ...
- 有 7k 个大小为 n - 2k 的调用
由此,我们立即得到 Ω(7n/2) 的下限,因为这是将要进行的调用次数。每个调用都做 O(n2) 的工作,所以我们可以获得 O(n27n/2) 的上限。真正的价值就在那里,虽然老实说我不知道如何弄清楚它是什么。很抱歉!
希望这会有所帮助!