我给你三个简短的代码:
第一个代码:
procedure Proc (n:integer)
begin
if n>0 then
begin
writeln('x')
Proc(n-2)
writeln('*');
Proc(n-2)
end
end
第二段代码:
procedure Proc (n:integer)
begin
if n>0 then
begin
writeln('*');
Proc(n-1)
end
end
第三个代码:
procedure Proc (n:integer)
begin
if n>0 then
begin
writeln('x')
Proc(n/2)
writeln('*');
Proc(n/2)
end
end
我想知道如何确定我给出的每个代码的计算复杂度,因为它会帮助我更好地理解..有人可以编写一个算法来逐步确定示例代码的计算复杂度,并且它可以将此算法应用于另一个代码示例吗?
答案 0 :(得分:0)
第一个问题:假设您知道对于n - 2的值,Proc称为T(n-1)次。因此,对于n的值,T(n)= 1 + 2T(n-2),因为将有一次调用Proc(n),这将调用Proc(n-2)两次。 T(n)= 1 + 2T(n-2)是河内塔的变体,其为T(n)= 1 + 2T(n-1)。这里有证明http://en.wikipedia.org/wiki/Tower_of_Hanoi来证明T(n)= 1 + 2T(n-1)= 2 ^ n-1。因此,T(n-1)= 1 + 2T((n-1)-1)= 1 + 2T(n-2)= 2 ^(n-1)-1。在你的情况下,T(n)= 1 + 2T(n-2)= 2 ^(n-1)-1。换句话说,在河内塔问题中减去每隔一个术语可以节省大约一半的电话。 2 ^(n-1)-1 = 2 ^ n / 2 - 1,其为O(2 ^ n)。
第二个问题:这更容易。 T(0)= 1且T(n)= 1 + T(n-1)。您可以通过多种不同方式解决这个问题,但其中一种方法是通过伸缩式实现:
T(n)= 1 + T(n-1)
T(n-1)= 1 +(n-2)
...
T(1)= 1 + T(0)
加上双方......
T(n)+ T(n-1)+ ... + T(1)= 1 + T(n-1)+ ... + 1 + T(0)= n + T(n- 1)+ ... + T(0)
减去类似的条款。
T(n)= n + T(0)= n + 1.所以这是O(n)。
第三个问题:与第一个类似。 T(0)= 1,假设我们知道对于n-1的值,你可以看到T(n)= 1 + 2 T(n / 2)。这里注意,T(n)= 1 + 2T(n / 2)< n + 2T(n / 2)。
因此解决2T(n / 2)+ n并推出重现:
T(n)= 2T(n / 2)+ n
T(n / 2)= 2T(n / 4)+ n / 2
因此T(n)= 4T(n / 4)+ n + n
T(n / 4)= 2T(n / 8)+ n / 4
因此T(n)= 8T(n / 8)n + n + n
......对于正k,看起来像T(n)= 2 ^ kT(n / 2 ^ k)+ kn。
通过归纳证明。 k = 1:给出T(n)= 2T(n / 2)+ n。这是我们的基本案例。 如果对于k-1为真,则对于k显示为真:
T(n)=(2 ^(k-1))T(n / 2 ^(k-1))+(k-1)n //归纳假设
T(n / 2 ^(k-1))= 2 T([n / 2 ^(k-1))] / 2)+ n / 2 ^(k-1))//给定复发< / p>
= 2T(n / 2 ^ k)+ n / 2 ^(k-1)
=&GT; T(n)=(2 ^ k)T(n / 2 ^ k)+ n +(k-1)n =(2 ^ k)T(n / 2 ^ k)+ kn。对于k来说是如此。
T(n)= 2 ^ kT(n / 2 ^ k)+ kn,选择合适的正k,例如k = ln(n)。
T(n)= 2 ^ ln(n)T(n / 2 ^ Ln(n))+ nln(n)= nT(1)+ nln(n)。
T(1)= 1,因为Proc刚刚结束。所以n(T(1))+ nln(n)= nln(n)+ n = O(nln(n))。
不幸的是,没有一个适合所有程序的复杂性。你必须根据具体情况采取它并找出问题。