Você está na página 1de 25

 Uma recorrência é uma equação que

descreve uma função em termos do seu valor


em entradas menores
O(1) se n  1
T (n)  
T (n  1)  1 se n  1
 Útil para análise de complexidade de
algoritmos recursivos ou do tipo “dividir para
conquistar”
 Número de multiplicações quando n = 1 é zero
T(1)  0
 Número de comparações quando n > 1 é 1
mais o número de multiplicações para n-1
T(n)  1  T(n  1)

int fatorial(int n) {
if(n == 1) { return 1; }
else { return n*fatorial(n-1); }
}
 O que é relevante pro custo?
 Número de marcações, número de chamadas
 Depende de quê? T(0)  0
 Parâmetro altura T(n)  2T(n  1)  1
void regua(int esq, dir, alt){
if(alt <= 0) return;
int m = (esq + dir) / 2;
marca(m, alt);
regua(esq, m, alt – 1);
regua(m, dir, alt – 1);
}
 Expande a árvore de recursão
 Calcula o custo em cada nível da árvore
 Soma os custos de todos os níveis
 Calcula a fórmula fechada do somatório

 Mas nem sempre funciona


 Número de chamadas recursivas
T(1)  1
T(2)  1
T(n)  T(n  1)  T(n  2)
int fib(int n) {
if(n < 3) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}
 Complicado de resolver pela árvore de
recorrência
 Árvore desbalanceada
 Somatório irregular
 Simples e direto
 Você chuta uma solução
 Verifica a solução por indução matemática

 Como fazer bons chutes?


 Usando árvores de recursão!
 Soluções de recorrências similares
 Refinamento iterativo
 Experiência
 Recorrência
T(1)  1
T(2)  1
T(n)  T(n  1)  T(n  2)
 Chute: exponencial
T(n)  O( 2 )
n

 Usaremos indução para provar


T(n)  c 2n
n1
supondo T(n  1)  c 2
 Esse chute é bom?
 Vamos encontrar um inferior para a recorrência
 Chute: exponencial!
T(n)  Ω3/ 2 
n

 Usaremos indução para provar


T(n)  c(3 / 2)n
 Provamos que T(n)  O( 2 ) e T(n)  Ω3/ 2
n n

 Logo, a função recursiva pra calcular o
n-ésimo número de Fibonacci tem custo
exponencial

 De fato T(n)  Θ( φn ) , onde


φ = (1 + 51/2)/2 = 1,61803 é a proporção
áurea
 Recorrência
T(1)  1
T(n)  2T(n / 2)  n

 Dá pra fazer direto pela árvore de recorrência


 Dá pra usar a árvore de recorrência pra fazer
um chute e usar o método da substituição
 Para facilitar, assuma que n é potência de 2
 Qual a solução da recorrência
T(1)  1
 
T(n)  2T n  log n
 Um parente distante de R(n)  2R(n / 2)  n
 Fazendo m = log(n), temos T(2m )  2T 2m / 2   m

 Fazendo S(m)  T( 2m ), temos


S(m)  S(m / 2)  m  O(m log m)  T(2m )
T(n)  O(log n log log n)
 Considere a recorrência
T(1)  1
T(n)  2T(n / 2)  1
 Vamos chutar T(n) = O(n)
 Usando o método da substituição
encontramos T(n)  cn  1, o que não implica
T(n)  cn
 Você pode chutar T(n) = O(n2)
 Mas nosso chute inicial T(n) = O(n) está correto
 Para eliminar o termo de ordem inferior
(+1), vamos subtrair um termo de ordem
inferior da nossa suposição pro passo indutivo
 Vamos provar que T(n) = O(n)
supondo T(n)  cn  b

 Obviamente, se provarmos T(n)  cn  b


então T(n)  cn
 Considere a recorrência que já resolvemos
T(1)  1
T(n)  2T(n / 2)  n
 Cuidado para não cometer o erro a seguir
 Chutar T(n) = O(n)
 Encontrar T(n) ≤ cn + n
 Falar que T(n) = O(n)
 No passo indutivo, precisamos encontrar
exatamente o que foi suposto
 Solução por árvore de recorrência
 Nem sempre dá pra resolver
 Solução por substituição
 Chute uma solução e verifique
▪ Provar exatamente o que foi suposto no passo indutivo
 Mecanismos para solução
▪ Transformação de variáveis
▪ Lembrar de soluções para recorrências similares
▪ Remoção de termos de ordem inferior
▪ Refinamento iterativo
 Método “receita de bolo” para resolver
recorrências do tipo
T (n)  aT(n / b)  f (n)
onde a  1, b  1 e f (n) positiva
 Este tipo de recorrência é típico de
algoritmos “dividir para conquistar”
 Dividem um problema em a subproblemas
 Cada subproblema tem tamanho n/b
 Custo para dividir e combinar os resultados é f(n)
 Seja T(n)  aT(n / b)  f (n)

Se f (n)  O(nlog b a ε ), com ε  0,


te mosT (n)  Θ(nlog b a ).
Se f (n)  Θ(nlog b a ),
te mosT (n)  Θ(nlog b a log n).
Se f (n)  Ω(nlog b a  ε ) para ε  0 e se af (n / b)  cf (n) para c  1,
te mosT (n)  Θ( f (n)).
 O resultado da recorrência depende da
comparação entre f (n) e nlogb a
 Note que a diferença entre f (n) e nlogb a
tem que ser polinomial, isto é, tem que ser
pelo menos nε
 Por causa disso o teorema mestre não se
aplica a todas recorrências
 Existe um intervalo entre os casos 1 e 2, e outro
intervalo entre os casos 2 e 3.
 Resolva a recorrência
T(n)  9T(n / 3)  n
usando o teorema mestre

 Caso 1 se aplica, temos


T(n)  Θ(n2 )
 Resolva a recorrência
T(n)  T(2n / 3)  1
usando o teorema mestre

 Caso 2 se aplica, temos


T(n)  Θ(log(n))
 Resolva a recorrência
T(n)  3T(n / 4)  n log n
usando o teorema mestre

 Caso 3 se aplica, temos


T(n)  Θ(n log n)
 Resolva a recorrência
T(n)  2T(n / 2)  n log n

 Nenhum caso do teorema mestre de aplica

 Descobrir um chute usando árvore de


recorrência e provar com método da
substituição

Você também pode gostar