Cap 2
Cap 2
Capítulo 2
Análise Assintótica da
Complexidade de Algoritmos
“Aconselho os meus alunos a terem muito cuidado quando decidirem não estudar
mais Matemática. Nesse momento, eles devem estar preparados para ouvirem
o som de portas se fechando.” -- James Caballero
c g(n)
f(n) = O(g(n))
f(n)
n
no
EXEMPLO: Suponha que f(n) = (3/2)n2 + (7/2)n - 4 e que g(n) = n2. A tabela
abaixo sugere que f(n) ≤ 2g(n) para n ≥ 6 e, portanto, parece que f(n) =
O(g(n)).
n f(n) g(n)
0 -4 0
1 1 1
2 9 4
3 20 9
4 34 16
5 51 25
6 71 36
7 94 49
8 120 64
É fácil verificar que, de fato, f(n) = O(g(n)) com um cálculo mais
grosseiro: f(n) ≤ 2n2+4n2 = 6n2 = 6g(n) para todo n.
f ( n)
Se 0 ≤ lim < ∞ , f(n) = O(g(n)).
n − >∞ g ( n)
Ordem Ω (Omega)
A expressão "f = O(g)" tem o significado matemático de "f ≤ g". Agora
precisamos de um conceito que tenha o significado de "f ≥ g".
DEFINIÇÃO: Dadas funções assintoticamente não-negativas f e g, dizemos que f
está na ordem Omega de g, e escrevemos f = Ω(g), ou f ∈ Ω(g), se f(n)
≥ c · g(n) para algum c positivo e para todo n suficientemente grande. Em
outras palavras, existe um número positivo c e um número positivo n0 tais que
f(n) ≥ c · g(n) para todo n ≥ n0. Neste caso, dizemos que g(n) é um limite
assintótico inferior para f(n). Na Figura 2 a seguir, a notação Ω é apresentada
graficamente.
f(n)
f(n) = Ω(g(n))
c g(n)
n
no
Figura 2 - A notação Ω dá um limite inferior para a função f(n). Dizemos que f(n)
é Ω(g(n)) se existem constantes positivas c e n0, de forma que à direita de n0, o
valor de f(n) está sempre acima ou igual a c.g(n).
f ( n)
Se 0 < lim ≤ ∞ , f(n) =Ω (g(n)).
n − >∞ g ( n)
Ordem ω
Ordem Θ (Theta)
Além dos conceitos de "f ≤ g" e de "f ≥ g", precisamos de um que tenha o
significado de "f = g".
DEFINIÇÃO: Dizemos que f e g estão na mesma ordem Theta e escrevemos
f = Θ(g) ou f ∈ Θ(g) se f = O(g) e f = Ω(g). Trocando em miúdos, f
= Θ(g) significa que existem números positivos c1 e c2 tais que c1·g(n) ≤
f(n) ≤ c2·g(n) para todo n suficientemente grande (n ≥ n0). Na Figura 3 a
notação Θ é apresentada graficamente.
c2 g(n)
f(n) = θ(g(n))
f(n)
c1 g(n)
n
no
f ( n)
Se 0 < lim < ∞ , f(n) =Θ (g(n)).
n − >∞ g ( n)
Propriedades de O, Ω e θ
(i) Reflexividade : f(n) = O(f(n)), f(n) = Ω(f(n)), f(n) = Θ(f(n))
(ii) Transitividade:
f(n) = O(g(n)) ≈ a ≤ b,
f(n) = Ω(g(n)) ≈ a ≥ b,
f(n) = Θ(g(n)) ≈ a = b,
f(n) = o(g(n)) ≈ a < b,
f(n) = ω(g(n)) ≈ a > b.
Instância de entrada
Figura 4 – A diferença entre o tempo para o pior caso e o tempo para o melhor
caso. Cada barra representa o tempo de execução de um algoritmo sobre uma
entrada diferente.
Exemplo:
n
1 1 1 1 1 1+ n 1 n
∑i. p
i =0
i = 0.
n +1
+ 1.
n +1
+ 2.
n +1
+ ... + n.
n +1
= (1 + 2 + ... + n).
n +1
=(
2
).n. =
n +1 2
Exemplo:
Faixa de
algoritmos n
aceitáveis
if (cond) {
seqüência de comandos 1
}
else {
seqüência de comandos 2
}
Neste caso, será executada a seqüência de comandos 1 ou a seqüência de
comandos 2. Assim, a complexidade de pior caso é dada por Max(seq1,
seq2). Por exemplo, se a seqüência 1 é O(N) e a seqüência 2 é O(1), a
complexidade de pior caso para a declaração inteira do if-then-else é O(N).
4. O tempo para executar um comando de repetição é a soma do tempo de
execução do corpo do laço mais o tempo de avaliar a condição de parada
multiplicado pelo número de iterações do laço.
Ex.: loop FOR
for (i = 0; i < N; i++) {
seqüência de comandos
}
O loop acima é executado N vezes, logo a seqüência de comandos é
executada também N vezes. Assumindo que a seqüência de comandos é
O(1), o tempo total para o loop é N * O(1), ou seja, O(N).
Ex.: loop FOR aninhado
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++) {
seqüência de comandos
}
}
O FOR mais externo executa N vezes. Cada vez que ele é executado, o FOR
mais interno executa M vezes. Como resultado a seqüência de comandos no
FOR mais interno é executa do N*M vezes. Assim, a complexidade é O(N*M).
Se a condição de parada do FOR mais interno fosse N, ao invés de M, a
complexidade do trecho acima seria O(N2), ou seja, complexidade
quadrática.
N − 2 N +1
No trecho acima, o comando c1 é executado ∑∑
i=2 j =1
1 vezes, ou seja
N −2
∑ ( N + 1) = ( N + 1)( N − 3) = N
i =2
2
− 2 N − 3 vezes.
Podemos também ter situações com um loop aninhado onde o número de vezes do
loop mais interno depende do valor do índice no loop mais externo, como no trecho a
seguir:
N −1 N −1
No trecho acima, o comando c1 é executado ∑∑
i =0 j =i
1 vezes, ou seja
N −1
N2 + N
∑
i =0
( N − i ) = ( N ) + ( N − 1) + ( N − 2) + ... + 1 =
2
vezes.
f(k); // O(1)
g(k); // O(k)
Exemplo:
T(n) = 2T(n/2)+n
T(1)=1
Resolvendo esta recorrência pelo método da iteração, temos:
T(n) = 2T(n/2) + n
= 2T(n/4)+n/2)+n = 4T(n/4)+2n
= 4(2T(n/8)+n/4)+2n = 8T(n/8)+3n
= 8(2T(n/16)+n/8)+3n = 16T(n/16)+4n
= ...
= 2kT(n/(2k))+kn
Lembramos que, no limite, temos que chegar no caso base da recursão,
k
ou seja, T(1). Para termos a fórmula acima em termos de T(1), n/(2 ) tem que
k
convergir para 1, e isso só acontece se 2 =n, ou seja, k=lgn. Temos então:
T(n) = 2lgn T(n/2 lgn))+(lgn)n
= nlg2 T(1)+nlgn
= n + nlgn
6.2. Teorema Mestre
Utilizado para resolver recorrências cujo caso geral é da forma T(n) = a.T(n/b) +
f(n), onde a≥1 e b>1 são constantes, n/b significa ⎡n/b⎤ ou ⎣n/b⎦, e f(n) é uma
função assintoticamente positiva.
Podemos interpretar esta relação de recorrência associada a um algoritmo
recursivo como: o algoritmo divide o problema em a partes iguais, cada uma de
tamanho b vezes menor que o problema original. O trabalho executado em cada
instância da recursão é determinado pela função f(n).
O método consiste no teste de três casos, tornando mais simples a solução
de muitas recorrências:
Exercícios de Fixação
1) Usando a definição da ordem O, demonstre a seguinte propriedade:
O(f(n)) + O(g(n)) = O(Max(f(n), g(n)))
2) Prove que an2 + bn + c = θ (n2), para quaisquer constantes a, b, c e a > 0.
3) Dê um exemplo de duas funções f(n) e g(n), f(n) ≠ g(n), onde f(n) = O(g(n)) e
g(n) = O(f(n)). Justifique.
4) Marque V ou F. Justifique.
2100 é O(1)
2n-1 = O(2n)
2n = ω(2n-1)
lg(lg n), n1/2 , n2, n2lgn, nlgn, lg n , nn, n3, 5!, 2lgn
a) A1 é θ(log n)
b) A2 é o([Link])
c) A3 é ω([Link] n)
d) A4 é Ω(ln2 n)
®
Análise Assintótica da Complexidade de Algoritmos Elton Silva 2007-2 16
9) Marque V ou F. Jusitifique .
10) João V. Lozz diz ter desenvolvido um algoritmo de complexidade O(n2/3) para
ordenar um conjunto de n elementos. Você compraria este algoritmo? Justifique
cuidadosamente a sua resposta. (obs.: sabe-se que a cota inferior e a cota
superior para o problema de ordenação é [Link]).
11) José $á Bido diz ter desenvolvido um algoritmo de complexidade O(n3/2) para
ordenar um conjunto de n elementos. Você compraria este algoritmo? Justifique
cuidadosamente a sua resposta.
12) Considere o algoritmo a seguir para encontrar o maior elemento e o menor
elemento de uma sequência A[1..n], n ≥ 1.
for i:= 2 to n do
if A[i] < x then x := A[i];
(1) i := 1;
(2) repetir
(3) se (A[i] <= 10)então x := A[i]
(4) senão se (A[i] <= 100) então y := A[i]
(5) senão se (A[i] <= 1000) então z := A[i];
(6) i := i + 1
(7) até (i > n);
if (x==y) {
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
seqüência de comandos;
}
}
for (i = 0; i < N; i++) {
seqüência de comandos
}
}
else {
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
for (k = 0; k < N; k++) {
seqüência de comandos;
}
}
}
}
®
Análise Assintótica da Complexidade de Algoritmos Elton Silva 2007-2 18
b)
(1) for (i=N; i>0; i--)
(2) for (j=N-1; j>1; j--)
(3) c1;
c)
(1) for (i=2; i<=N-3; i++)
(2) for (j=N; j>i; j--)
(3) c1;
21) João V. Lozz diz ter desenvolvido um algoritmo de pesquisa recursivo cuja
relação de recorrência é dada por:
T(n) = 3 T(n/3) + n
T(1) = 1
23) Um certo algoritmo A tem uma estrutura recursiva que permite descrever
seu tempo de computação por:
T(n) = T(⎣n/3⎦) + T(⎣n/5⎦) + n
T(1) = 1,
onde n representa o tamanho da entrada. Qual a ordem de complexidade de
pior caso desse algoritmo?
24) Encontre a ordem de complexidade do programa XPTO, no melhor caso e
no pior caso.
(1) PROGRAM XPTO;
(2) PROCEDURE P(N: INT);
(3) {
(4) IF (N > 1) THEN {
(5) //DIVIDE N EM DUAS INSTÂNCIAS N1 E N2, DE IGUAL TAMANHO, COM CUSTO N2
(6) P(N1);
(7) P(N2)
(8) }
(9) };
(10) FUNCTION F(N: INT): INT;
(11) {
(12) IF (N = 0) THEN F := 1
(13) ELSE F := 3 * F(N-2)
(14) };
(15) {
(16) read(x,y); //x e y são inteiros positivos, x é par e y>=2
(17) IF (X < Y) THEN P(X)
(18) ELSE Z := F(Y);
(19) }
Bibliografia
Algoritmos: Teoria e Prática, T. H. Cormen, C. E. Leiserson, R. L. Rivest & C.
Stein, Editora Campus, 1991
Computer Algorithms, E. Horowitz, S. Sahni & S. Rajasekaran, Computer
Science Press, 1998.
Data Structures and Algorithms, Aho, A., Hopcroft, J. F. & Ullman, J. D.
Fundamentals of Computer Algorithms, Horowitz, E. & Sahni, S.
Projeto de Algoritmos: fundamentos, análise e exemplos da Internet, Michael
Goodrich, Bookman, 2004.
Projeto e Análise de Algoritmos, Elton Silva, 2006 (anotações do professor)
®
Análise Assintótica da Complexidade de Algoritmos Elton Silva 2007-2 21
∑ ai = a k + a k +1 + a k + 2 + ... + a n
i=k
∑1 = n
i =1
(n − k + 1) termos
n n
∑ cai = c∑ ai
i=k i=k
n n n Atenção:
∑ ai ± bi = ∑ ai ± ∑ bi n n n
i=k i =k i =k
∑ ai * bi ≠ ∑ ai * ∑ bi
i =k i =k i=k
n n n
∑a
i =k
i / bi ≠ ∑ ai / ∑ bi
i =k i =k
Soma Aritmética (P.A) n
n(n + 1)(2n + 1)
n
(a + a n )n Soma de Quadrados ∑i 2
=
∑
i =1
a i = a1 + a 2 + ... + a n = 1
2
i =0 6
n 2 (n + 1) 2
n
Soma de Cubos ∑ i =
3
i =0 4
Soma Geométrica (P.G)
n
x n +1 − 1
∑
i =0
x =x .i
x −1
0
,x ≠1
Exponencial e Logaritmos
x0 = 1 log b 1 = 0 Convenções:
x −a = 1 / x a a = b logb a lg a = log 2 a
x a +b
= x .x
a b log c (a.b) = log c a + log c b ln a = log e a e = 2,71...
x a −b = x a / x b log c (a / b) = log c a − log c b log a = log10 a
x a .b
= (x ) = (x )
a b b a log b a = n. log b a
n
log a + b = (log a) + b
a =n
log b n log b a
log k n = (log n) k
log b a = (log c a ) /(log c b) log log n = log(log n)
log b a = 1 /(log a b)
Piso e Teto
x∈ ℜ x-1 < ⎣x⎦ ≤ x ≤ ⎡x⎤ < x+1
Regra de L’Hôpital
O limite da razão de duas funções é indeterminado se ambas as funções tendem
a zero, ou ambas tendem a infinito. Se f(x) e g(x) são diferenciáveis, com limites
indeterminados, então lim ( f ( x ) / g ( x )) = lim ( f ' ( x ) / g ' ( x )) .
x − >∞ x − >∞
Derivadas:
Obs.: se lim f(n)/g(n)=0, f(n) = o(g(n)) 2. Se f(n)= Θ(nlogba), então T(n)= Θ([Link] n)
f ( n)
(ii) Se 0 < lim ≤ ∞ , f(n) = Ω(g(n)) 3. Se f(n)= Ω(n(logba) + ε) para uma constante ε>0,
n − >∞ g ( n) e se af(n/b) ≤cf(n), para alguma constante c<1 e
n suficientemente grande então T(n)= Θ(f(n))
Obs.: se lim f(n)/g(n)=∞, f(n) = ω(g(n))
Relações-padrão
f ( n)
(iii) Se 0 < lim < ∞ , f(n) = Θ(g(n)) • T(n)=T(n/c) + k, k,c const, c>1, T(n)=O(logcn)
n − > ∞ g ( n) • T(n)=cT(n/c) + k, k,c const, c>1, T(n)=O(n)
• T(n)=aT(n/c) + k, k, a, c const, a>c, c>1, T(n)=O(nlogca)
• T(n)=aT(n/c) + kn, k, a, c const, c>1,
a<c, T(n)=O(n)
a=c, T(n)=O(nlgn)
a>c, T(n)=O(nlogca)
T(n)= n log b a [T(1) + u(n)], a≥1, b>1 h(n) (teste) u(n) (complexidade)
Combinatória Básica
n! n! n
P(n, r) =
(n − r )!
0 ≤r ≤ n C(n, r) =
r!(n − r )!
0≤r≤n (a+b)n = ∑ C ( n, k ) a
k =0
n−k
bk
P(n, r) = nr
C(n+r-1, r) =
(n + r − 1)!
r!( n − 1)!