示例代码计算复杂度的确定
Determination of computational complexity of sample code
我给你三个短码:
第一个代码:
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
我想知道如何确定我给出的每个代码的计算复杂度,因为它将帮助我更好地理解..有人可以编写一个算法来逐步确定示例代码的计算复杂度,并这样做以便可以将此算法应用于其他代码示例?
第一个问题:假设你知道对于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) = 2 T(n/2) + n
T(n/2) = 2 T(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) = 2 T(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)) //给定递归
= 2T(n/2^k)+n/2^(k-1)
=> 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))。
不幸的是,对于复杂性,没有一个放之四海而皆准的程序。得具体情况具体分析,找出问题所在。
我给你三个短码:
第一个代码:
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
我想知道如何确定我给出的每个代码的计算复杂度,因为它将帮助我更好地理解..有人可以编写一个算法来逐步确定示例代码的计算复杂度,并这样做以便可以将此算法应用于其他代码示例?
第一个问题:假设你知道对于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) = 2 T(n/2) + n
T(n/2) = 2 T(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) = 2 T(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)) //给定递归
= 2T(n/2^k)+n/2^(k-1)
=> 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))。
不幸的是,对于复杂性,没有一个放之四海而皆准的程序。得具体情况具体分析,找出问题所在。