ANÁLISE DE ALGORITMOS www.ime.usp.br/ pf/analise de algoritmos/ Paulo Feofiloff Transparências baseadas no Introduction to Algorithms de Cormen, Leiserson, Rivest, Stein A análise de algoritmos é uma disciplina de engenharia. Um engenheiro civil, por exemplo, tem métodos e tecnologia para prever o comportamento de uma estrutura antes de constui-la. Da mesma forma, um projetista de algoritmos deve ser capaz de prever o comportamento de um algoritmo antes de implementá-lo. CLRS = Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms AU = Aho, Ullman, Foundations of Computer Science 1
AULA 1 Piso, teto, log etc. CLRS 3.2, A.1 AU 2.9 2
Definições x := inteiro i tal que i x < i + 1 x := inteiro j tal que j 1 < x j Exercício 1.A Desenhe os gráficos das funções x e x para x não-negativo. Exercício 1.B Mostre que n n 1 n e 2 2 2 para qualquer inteiro n 1. n 2 n 2 n + 1 2 Exercício 1.C É verdade que x + y = x + y para quaisquer x e y? Exercício 1.D Desenhe os gráficos das funções lg x e 2 x para x inteiro não-negativo. 3
Exercício 1.E Explique o significado da expressão log 3/2 n. Exercício 1.F Calcule 5 log 5 n, log 3 3 n e lg2 n. Exercício 1.G Qual a relação entre log 8 n e log 2 n? Exercício 1.H Se i := lg n, qual a relação entre n e 2 i? Se j := lg n, qual a relação entre n e 2 j? Exercício 1.I É verdade que lg n + 1 = lg(n + 1) para todo inteiro n 1? Exercício 1.J Escreva um algoritmo que calcule lg n. 4
TAREFA 1 Exercício 1.L Mostre que para qualquer número real x tem-se x 1 < x x x < x + 1. Exercício 1.M Mostre que n/2 + n/2 = n para todo inteiro positivo n. Exercício 1.N Mostre que x + y x + y, com igualdade se e somente se x + y 1 < x + y. Encontre uma fórmula análoga para. Exercício 1.O Se c é inteiro e x é racional, é verdade que cx = c x? Exercício 1.P Use a notação para representar o resto da divisão de n por 7. Exercício 1.Q É verdade que 2 2n/3 /3 = 4n/9? É verdade que 2 2n/3 /3 = 4n/9? Exercício 1.R É verdade que n/2 /2 = n/4? Exercício 1.S Se n, a, b são inteiros positivos, é verdade que n/a /b = n/ab? Exercício 1.T É verdade que lg n lg(n 1) para todo inteiro n 2? É verdade que lg n lg(n + 1) para todo inteiro n 1? Exercício 1.U Prove que para qualquer número racional x > 1 tem-se lg x lg x lg x lg x lg x Exercício 1.V Quanto vale 1/2 + 1/4 + 1/8 + + 1/2 n +? 5
AULA 2 Introdução à AA CLRS 2.1 2.2 AU 3.3, 3.6 6
Exercício 2.A Quanto vale S no fim do algoritmo? 1 S 0 2 para i 2 até n 2 faça 3 para j i até n faça 4 S S + 1 Escreva um algoritmo mais eficiente que tenha o mesmo efeito. Solução Se n 4 então no fim da execução das linhas 1 4, S = (n 1) + (n 2) + + 4 + 3 = (n 3)(n + 2)/2 = 1 2 n2 1 2 n 3. 7
Análise da ordenação por inserção Algoritmo rearranja A[1.. n] em ordem crescente (A[1.. n] é crescente se A[1] A[n]) ORDENA-POR-INSERÇÃO (A, n) 1 para j 2 até n faça 2 chave A[j] 3 i j 1 4 enquanto i 1 e A[i] > chave faça 5 A[i + 1] A[i] 6 i i 1 7 A[i + 1] chave O algoritmo faz o que promete? Invariante: antes de cada execução do bloco de linhas 2 7, A[1.. j 1] é crescente 1 j n 22 33 33 33 44 55 11 99 22 55 77 Prove! 8
Quantas atribuições ( ) algoritmo faz? 3 i j 1 2 j n 4 enquanto i 1 e A[i] > chave faça 5 A[i + 1] A[i] 6 i i 1 linha atribuições 3 1 4 0 5 j 1 n 1 6 n 1 3 6 2n 1 9
1 para j 2 até n faça j j + 1 escondido 2 chave A[j] 3 LINHAS 3 6 7 A[i + 1] chave linha atribuições 1 n 1 + 1 2 n 1 3 6 (n 1)(2n 1) 7 n 1 total 2n 2 1 10
Análise mais fina do número de atribuições: linha atribuições 1 n 1 + 1 2 n 1 3 n 1 4 0 5 1 + 2 + + (n 1) = n(n 1)/2 6 1 + 2 + + (n 1) = n(n 1)/2 7 n 1 total n 2 + 3n 3 n n 2 + 3n 3 n 2 1 1 1 2 7 4 3 15 9 10 127 100 100 10297 10000 1000 1002997 1000000 10000 100029997 100000000 100000 10000299997 10000000000 n 2 domina os outros termos 11
Exercício 2.B Se cada linha de código consome 1 unidade de tempo, qual o consumo total? 1 para j 2 até n faça 2 chave A[j] 3 i j 1 4 enquanto i 1 e A[i] > chave faça 5 A[i + 1] A[i] 6 i i 1 7 A[i + 1] chave Solução linha todas as execuções da linha 1 n 2 n 1 3 n 1 4 2 + 3 + + n = (n 1)(n + 2)/2 5 1 + 2 + + (n 1) = n(n 1)/2 6 1 + 2 + + (n 1) = n(n 1)/2 7 n 1 total 3 2 n2 + 7 2 n 4 12
TAREFA 2 Exercício 2.C (bom!) Quanto vale S no fim do seguinte algoritmo? 1 S 0 2 i n 3 enquanto i > 0 faça 4 para j 1 até i faça 5 S S + 1 6 i i/2 Exercício 2.D Prove o invariante do algoritmo ORDENA-POR-INSERÇÃO. Exercício 2.E Quantas comparações faz o algoritmo ORDENA-POR-INSERÇÃO, no pior caso, ao receber um vetor A[1.. n]? Exercício 2.F Quantas atribuições faz o algoritmo abaixo? s 0 para i 1 até n faça s s + i devolva s Escreva um algoritmo melhorado que produza o mesmo efeito com menos atribuições. Exercício 2.G (AU 3.7.1) O algoritmo abaixo opera sobre um vetor A[1.. n]. Quantas atribuições ele faz no pior caso? Quantas comparações? 1 s 0 2 para i 1 até n faça 3 s s + A[i] 4 m s/n 5 k 1 6 para i 2 até n faça 7 se (A[i] m) 2 < (A[k] m) 2 8 então k i 9 devolva k 13
Exercício 2.H (AU 3.7.2) O fragmento abaixo opera sobre uma matriz A[1.. n, 1.. n]. Quantas atribuições faz? 1 para i 1 até n 1 faça 2 para j i + 1 até n faça 3 para k i até n faça 4 A[j, k] A[j, k] A[i, k] A[j, i]/a[i, i] Exercício 2.I (AU 3.7.3*) Quantas atribuições faz o algoritmo? SumPowersOfTwo (n) 1 s 0 2 para i 1 até n faça 3 j i 4 enquanto 2 j/2 = j faça 5 j j/2 6 s s + 1 7 devolva s 14
AULA 3 Análise assintótica Notação O CLRS 3.1 AU 3.4, p.96 100 (muito bom!) 15
Funções de n: 5n 2 9n 4n + 8 n/3 + 4 2 n + 7 2 n 3 log n Qual é maior: n 2 9 ou 4n + 8? Qual cresce mais? Comparação assintótica (i.e., para n grande) O(f(n)) funções q não crescem mais rápido que f(n) funções menores ou iguais a um múltiplo de f(n) n 2 + 99n é O(n 2 ) 33n 2 é O(n 2 ) 9n + 2 é O(n 2 ) 0,00001n 3 200n 2 não é O(n 2 ) 16
Definição T(n) = O(f(n)) se existem c e n 0 positivos tais que para todo n n 0. 0 T(n) c f(n) Mais informal: T(n) = O(f(n)) se existe c > 0 tq 0 T(n) c f(n) para todo n suficientemente grande. T(n) = O(f(n)) deve ser entendido como T(n) O(f(n)) Exemplo Se T(n) 500f(n) para todo n 10 então T(n) = O(f(n)) Exemplo 10n 2 = O(n 3 ) Prova: Para n 0, temos 0 10n 2 10 n 3 Outra prova: Para n 10, temos 0 10n 2 n n 2 = n 3 17
Exercício 3.A Prove que n 2 + 10n + 20 = O(n 2 ) Exercício 3.B Prove que 300 = O(1) Exercício 3.C Prove que n/3 = O(n) É verdade que n = O( n/3 )? Exercício 3.D Prove que lg n = O(log 10 n) Exercício 3.E Prove que n = O(2 n ) Exercício 3.F Prove que lg n = O(n) Exercício 3.G Prove que n/1000 não é O(1) Exercício 3.H Prove que 1 2 n2 não é O(n) 18
Exercício 3.I Suponha T definida para n = 0,1,... Se T(n) = O(1), mostre que existe c tal que T(n) c para todo n 0. Se T(n) = O(n), mostre que existe c tal que T(n) c n para todo n 1. 19
TAREFA 3 Exercício 3.J Prove que n 2 + 999n + 9999 = O(n 2 ). Exercício 3.K Prove que 1 2 n(n + 1) = O(n2 ). Exercício 3.L É verdade que 1 100 n2 999n 9999 = O(n)? Justifique. Exercício 3.M Suponha que f(n) = n 2 quando n é par e f(n) = n 3 quando n é ímpar. É verdade que f(n) = O(n 2 )? É verdade que f(n) = O(n 3 )? É verdade que n 2 = O(f(n))? É verdade que n 3 = O(f(n))? Exercício 3.N É verdade que n 2 = O(2 n )? Exercício 3.O É verdade que lg n = O( n)? Exercício 3.P Suponha f(n) = 64nlg n e g(n) = 8n 2, com n inteiro positivo. Para que valores de n temos f(n) g(n)? Exercício 3.Q (bom!) Suponha T e f definidas para n = 1,2,... Mostre que se T(n) = O(f(n)) e f(n) > 0 para n 1 então existe c tal que T(n) c f(n) para todo n 1. Exercício 3.R (bom!) Faz sentido dizer T(n) = O(n 2 ) para n 3? 20
TAREFA ADICIONAL Exercício 3.S É verdade que 2 n = O(n)? É verdade que n = O(lg n)? Justifique. Exercício 3.T É verdade que n + n é O(n)? É verdade que n é O( n)? É verdade que n 2/3 é O( n)? É verdade que n + 1000 é O(n)? Exercício 3.U É verdade que lg n = O(n 1/2 )? É verdade que n = O(lg n)? É verdade que lg n = O(n 1/3 )? Justifique. (Sugestão: prove, por indução, que lg x x para todo número real x 1.) Exercício 3.V É verdade que lg n = O(lg n)? 21
AULA 4 Análise de algoritmos iterativos CLRS 2.1 2.2 AU 3.3, 3.6 (muito bom) 22
Análise com notação O ORDENA-POR-INSERÇÃO (A, p, r) 1 para j p + 1 até r faça 2 chave A[j] 3 i j 1 4 enquanto i p e A[i] > chave faça 5 A[i + 1] A[i] 6 i i 1 7 A[i + 1] chave Quanto tempo o algoritmo consome? Tamanho de uma instância: n := r p + 1 linha consumo de todas as execuções da linha 1 O(n) 2 O(n) 3 O(n) 4 no(n) = O(n 2 ) 5 no(n) = O(n 2 ) 6 no(n) = O(n 2 ) 7 O(n) total O(3n 2 + 4n) = O(n 2 ) 23
Explicação: Bloco de linhas 4 6 é executado n vezes; cada execução consome O(n); todas juntas consomem no(n). Êpa! Quem garante que no(n) = O(n 2 )? Quem garante que O(n 2 ) + O(n 2 ) + O(n 2 ) = O(3n 2 )? Quem garante que O(3n 2 + 4n) = O(n 2 )? Veja exercícios na próxima aula. Conclusão: O algoritmo consome O(n 2 ) unidades de tempo Notação O cai como uma luva! 24
Análise da intercalação Dados A[p.. q] e A[q+1.. r] crescentes, rearranjar A[p.. r] em ordem crescente. Para que valores de q o problema faz sentido? p q r A 11 33 55 77 99 22 44 66 88 B INTERCALA (A, p, q, r) 00 crie vetor B[p.. r] 01 para i p até q faça 02 B[i] A[i] 03 para j q + 1 até r faça 04 B[r + q + 1 j] A[j] 05 i p 06 j r 07 para k p até r faça 08 se B[i] B[j] 09 então A[k] B[i] 10 i i + 1 11 senão A[k] B[j] 12 j j 1 25
00 crie vetor B[p.. r] 01 para i p até q faça 02 B[i] A[i] 03 para j q + 1 até r faça 04 B[r + q + 1 j] A[j] 05 i p 06 j r 07 para k p até r faça 08 se B[i] B[j] 09 então A[k] B[i] 10 i i + 1 11 senão A[k] B[j] 12 j j 1 Quanto tempo consome em função de n := r p + 1? linha consumo de todas as execuções da linha 00 O(n) 01 04 O(n) 05 06 O(1) 07 no(1) = O(n) 08 no(1) = O(n) 09 12 no(1) = O(n) Consumo total = O(5n + 1) = O(n) 26
TAREFA 4 Exercício 4.A Problema: rearranjar um vetor A[p.. r] em ordem crescente. Escreva um algoritmo de seleção para o problema. Analise a correção do algoritmo (ou seja, encontre e prove os invariantes apropriados). Analise o consumo de tempo do algoritmo; use notação O. Exercício 4.B Analise a correção e o consumo de tempo do seguinte algoritmo: EXERC (A, p, r) 1 q (p + r)/2 2 ORDENA-POR-INSERÇÃO(A, p, q) 3 ORDENA-POR-INSERÇÃO(A, q + 1, r) 4 INTERCALA(A, p, q, r) 27
AULA 5 Mais notação O CLRS 3.1 AU 3.5, p.101 108 28
Exercício 5.A Interprete e prove a afirmação O(n 2 ) + O(n 2 ) + O(n 2 ) = O(3n 2 ). Exercício 5.B Interprete e prove a afirmação no(n) = O(n 2 ). Exercício 5.C Interprete e prove a afirmação O(3n 2 + 4n) = O(n 2 ). Exercício 5.D (propriedade transitiva) Suponha T(n) = O(f(n)) e f(n) = O(g(n)). Mostre que T(n) = O(g(n)). Dê um exemplo interessante. Exercício 5.E (regra da soma, caso especial) Suponha que T(n) = O(f(n)) e mostre que T(n) + f(n) = O(f(n)). Dê um exemplo interessante. 29
Exercício 5.E (regra da soma, geral) Suponha T 1 (n) = O(f 1 (n)) e T 2 (n) = O(f 2 (n)). Se f 1 (n) = O(f 2 (n)), mostre que T 1 (n) + T 2 (n) = O(f 2 (n)). Exercício 5.F O que significa T(n) = n 2 + O(n)? Mostre que se T(n) = n 2 + O(n) então T(n) = O(n 2 ). 30
TAREFA 5 Exercício 5.G O que significa T(n) = no(lg n)? Mostre que T(n) = no(lg n) se e só se T(n) = O(nlg n). Exercício 5.H Interprete e prove a afirmação 7 O(n) = O(n). Exercício 5.I Interprete e prove a afirmação O(n) + O(n) = O(n). Exercício 5.J Prove que O(n) = O(n 2 ). É verdade que O(n 2 ) = O(n)? Exercício 5.K Interprete e prove a afirmação (n + 2) O(1) = O(n). Exercício 5.L Interprete e prove a afirmação O(1) + + O(1) = O(n). }{{} n+2 Exercício 5.M Prove que O(1) + O(1) + O(1) = O(1). É verdade que O(1) = O(1) + O(1) + O(1)? Exercício 5.N Interprete e prove a afirmação O(f) + O(g) = O(f + g). 31
AULA 6 Cotas inferiores: notação Ω CLRS 3.1 32
Definição T(n) = Ω(f(n)) se existem c e n 0 positivos tq para todo n n 0 0 c f(n) T(n) Mais informal: T(n) = Ω(f(n)) se existe c > 0 tq 0 cf(n) T(n) para todo n suficientemente grande. Exemplo: Se T(n) 0.001n 2 para todo n 8 então T(n) = Ω(n 2 ). Exemplo: INTERCALA é O(n) e também Ω(n). Fácil: T = Ω(f) f = O(T) Definição T = Θ(f) T = O(f) e T = Ω(f) 33
Alguns nomes de classes Θ: Θ(1) constante Θ(log n) logarítmica Θ(n) linear Θ(nlog n) nlog n Θ(n 2 ) quadrática Θ(n 3 ) cúbica Θ(2 n ) exponencial Exercício 6.A Já sabemos que ORDENA-POR-INSERÇÃO é O(n 2 ). Mostre que o algoritmo é Ω(n). Exercício 6.B Mostre que ORDENA-POR-INSERÇÃO é Ω(n 2 ) no pior caso. Exercício 6.C Mostre que ORDENA-POR-INSERÇÃO é O(n) no melhor caso. 34
TAREFA 6 Exercício 6.D Prove que n 2 + 10n + 20 = Ω(n 2 ). Prove que n 2 10n 20 = Θ(n 2 ). Exercício 6.E Prove que n = Ω(lg n). Exercício 6.F Prove que lg n = Θ(log 10 n). Exercício 6.G É verdade que 2 n = Ω(3 n )? Exercício 6.H É verdade que 2n 3 + 5 n = Θ(n 3 )? Exercício 6.I Suponha que os algoritmos A e B só dependem de um parâmetro n. Suponha ainda que A consome S(n) unidades de tempo enquanto B consome T(n) unidades de tempo. Quero provar que algoritmo A é pelo menos tão eficiente quanto o algoritmo B (no sentido assintótico). Devo mostrar que existe f(n) tal que S(n) = O(f(n)) e T(n) = O(f(n))? S(n) = O(f(n)) e T(n) = Ω(f(n))? S(n) = Ω(f(n)) e T(n) = O(f(n))? S(n) = Ω(f(n)) e T(n)Ω(f(n))? Que devo fazer para mostrar que A é mais eficiente que B? Exercício 6.J Mostre que o consumo de tempo do algoritmo INTERCALA é Θ(n), sendo n o número de elementos do vetor que o algoritmo recebe. 35
AULA 7 Recursão AU 2.6, 2.7, 2.9 36
Recursão: resolve uma instância do problema a partir das soluções de instâncias menores "To understand recursion, we must first understand recursion. Exercício 7.A Problema: verificar se v é elemento de A[p.. r]. (Para q valores de p e r faz sentido?) Escreva algoritmo recursivo. Exercício 7.B Problema: verificar se v é elemento de vetor crescente A[p.. r]. Escreva algoritmo recursivo de busca linear e outro de busca binária. Exercício 7.C Escreva versão recursiva da ordenação por inserção. 37
TAREFA 7 Exercício 7.D (Versão sofisticada de busca) Problema: verificar se v é elemento de vetor crescente A[p.. r]. Escreva um algoritmo que devolva j tal que A[j] v < A[j + 1]. Quais os possíveis valores de j? Escreva duas versões: uma linear e uma binária. Prove que os seus algoritmos estão corretos. Exercício 7.E Escreva uma versão recursiva do algoritmo de ordenação por seleção. 38
AULA 8 Recorrências CLRS 4.1 4.2 AU 3.9, 3.11 39
Recorrência = = fórmula que define uma função em termos d ela mesma = algoritmo recursivo que calcula uma função Exemplo 1 T(1) = 1 T(n) = T(n 1) + 3n + 2 para n = 2,3,4,... Define função T sobre inteiros positivos: n T(n) 1 1 2 9 3 20 4 34 5 51 6 71 40
Resolver uma recorrência = = obter uma fórmula fechada para T(n) Método da substituição: chute fórmula e verifique por indução Exemplo 1 (continuação) Eu acho que T(n) = 3 2 n2 + 7 2 n 4. Verificação: Se n = 1 então T(n) = 1 = 3 2 + 7 2 4. Tome n 2 e suponha que a fórmula está certa para n 1: T(n) = T(n 1) + 3n + 2 Bingo! hi = 3 2 (n 1)2 + 7 2 (n 1) 4 + 3n + 2 = 3 2 n2 3n + 3 2 + 7 2 n 7 2 4 + 3n + 2 = 3 2 n2 + 7 2 n 4. 41
Como adivinhei fórmula fechada? Árvore da recorrência: T(n) 3n+2 3n+2 3n+2 3n+2 T(n 1) 3(n 1)+2 3n 1 3n 1 T(n 2) 3(n 2)+2 3n 4 T(n 3). 8 T(1) 1 + n 1 níveis T(n) = (3n + 2) + (3n 1) + + 8 + T(1) = 3 2 n2 + 7 2 n 4 42
Exemplo 2 T(1) = 1 T(n) = 2T(n/2) + 7n + 2 para n = 2,3,4,5,... Não é uma recorrência! Não faz sentido! Exemplo 3 G(1) = 1 G(n) = 2G(n/2) + 7n + 2 para n = 2,4,..,2 i,.. n G(n) 1 1 2 18 4 66 8 190 16 494 Fórmula fechada: G(n) =? 43
Acho que G é da forma nlg n n G(n) 6nlg n 7nlg n 8nlg n n 2 1 1 0 0 0 1 2 18 12 14 16 4 4 66 48 56 64 16 8 190 144 168 192 64 16 494 384 448 512 256 32 1214 960 1120 1280 1024 64 2878 2304 2688 3072 4096 128 6654 5376 6272 7168 16384 256 15102 12288 14336 16384 65536 44
Acho que a fórmula fechada é para n = 1,2,4,8,16,... G(n) = 7nlg n + 3n 2 Prova: Se n = 1 então G(n) = 1 = 7 1lg1 + 3 1 2. Se n 2 então Bingo! G(n) = 2G( n 2 ) + 7n + 2 hi = 2(7 n 2 lg n 2 + 3 n 2 2) + 7n + 2 = 7n(lg n 1) + 3n 4 + 7n + 2 = 7nlg n 7n + 3n 2 + 7n = 7nlg n + 3n 2 45
Como adivinhei fórmula fechada? Árvore da recorrência: G(n) 7n + 2 / \ G( n 2 ) G(n 2 ) 7n + 2 / \ 7 n 2 + 2 7n 2 + 2 / \ / \ G( n 4 ) G(n 4 ) G(n 4 ) G(n 4 ) 7n + 2 / \ 7 n 2 + 2 7n 2 + 2 / \ / \ 7 n 4 + 2 7n 4 + 2 7n 4 + 2 7n 4 + 2.... G(1) G(1)...... G(1) G(1) total de 1 + lg n níveis 46
nível soma no nível 0 7n + 2 1 7n + 4 2 7n + 8.. k 1 7n + 2 k k 2 k G(1) n = 2 k G(n) = 7n + 2 1 + 7n + 4 2 + + 7n + 2 lg n + 2 lg n G(1) = 7nlg n + (2 + 4 + + 2 lg n ) + 2 lg n = 7nlg n + 2 2 lg n 2 + n = 7nlg n + 2n 2 + n = 7nlg n + 3n 2 Lembrete: x 0 + + x k = xk+1 1 x 1 CLRS (A.5), p.1060 47
Exemplo 3 (continuação) É mais fácil mostrar que G(n) = O(n lg n). Vou provar que G(n) 9nlg n quando n = 2,4,8,16,..,2 i,... Prova: Se n = 2, G(n) = 18 = 9 2 lg2. Se n 4, G(n) = 2G(n/2) + 7n + 2 hi 2 9(n/2)lg(n/2) + 7n + 2 = 9n(lg n 1) + 7n + 2 = 9nlg n 2n + 2 < 9nlg n (pois n > 1) Da linha 1 para a linha 2, a hipótese de indução vale pois 2 n/2 < n. 48
TAREFA 8 Exercício 8.A Seja T a função definida pela recorrência T(1) = 1 T(n) = T(n 1) + 2n 2 para n = 2,3,4,5,... Verifique que a recorrência é honesta, ou seja, de fato define uma função. A partir da árvore da recorrência, adivinhe uma boa cota assintótica para T(n); dê a resposta em notação O. Prove a cota pelo método da substituição. Exercício 8.B Resolva a recorrência T(1) = 1 T(n) = T(n 2) + 2n + 1 para n = 2,3,4,5,... Desenhe a árvore da recorrência. Dê a resposta em notação O. Exercício 8.C Resolva a recorrência T(1) = 1 T(2) = 2 T(n) = T(n 2) + 2n + 1 para n = 3,4,5,6,... Exercício 8.D Resolva a recorrência Exercício 8.E Resolva a recorrência Exercício 8.F Resolva a recorrência T(1) = 1 T(n) = T(n/2) + 1 para n = 2,3,4,5,... T(1) = 1 T(n) = T( n/2 ) + 1 para n = 2,3,4,5,... T(1) = 1 T(n) = T( n/2 ) + n para n = 2,3,4,5,... 49
Exercício 8.G Resolva a recorrência T(1) = 1 T(n) = 2T( n/2 ) + n para n = 2,3,4,5,... Exercício 8.H Resolva a recorrência T(1) = 1 T(n) = 2T( n/2 ) + n para n = 2,3,4,5,... 50
AULA 9 Recorrências com notação O CLRS 4.1 4.2 AU 3.9, 3.11 51
Classe O da solução de uma recorrência Não faço questão de solução exata: basta solução aproximada Exemplo (n é potência de 2): G(1) = 1 G(n) = 2G(n/2) + 7n + 2 para n 2 Solução exata (n é potência de 2): G(n) = 7nlg n + 3n 2 Solução aproximada: G(n) = O(nlg n) Em geral, é mais fácil obter e provar solução aproximada que solução exata 52
Dica prática (sem prova) A solução da recorrência T(1) = 1 T(n) = 2T( n/2 ) + 7n + 2 para n = 2,3,4,5,.. está na mesma classe Θ que a solução de T (1) = 1 T (n) = 2T (n/2) + n para n = 2 1,2 2,2 3,... e na mesma classe Θ que a solução de T (4) = 10 T (n) = 2T (n/2) + n para n = 2 3,2 4,2 5,... 53
Recorrências com O do lado direito A recorrência T(n) = 2T(n/2) + O(n) representa todas as recorrências da forma T(n) = 2T(n/2) + F(n) em que F(n) = O(n) Melhor: representa todas as recorrências do tipo T (n) = a para n = n 0 1 T (n) 2T ( n/2 ) + cn para n n 0 quaisquer que sejam a, c > 0 e n 0 > 0 (poderíamos tomar n 0 = 1; veja ex 3.I) Também representa todas as do tipo T (n) = a para n = 2 k 1 T (n) 2T (n/2) + cn para n = 2 k,2 k+1,... quaisquer que sejam a, c > 0 e k > 0 As soluções exatas vão depender de a, c, n 0, k; mas todas estarão na mesma classe O (especificamente, em O(n lg n)) 54
Dicas práticas recorrência condição solução T(n) = T(n 1) + 4n 3 Θ(n 3+1 ) T(n) = 6T(n 1) + 4n 3 Θ(6 n ) T(n) = at(n/5) + 4n 3 a < 5 3 Θ(n 3 ) T(n) = at(n/5) + 4n 3 a = 5 3 Θ(n 3 log n) T(n) = at(n/5) + 4n 3 a > 5 3 Θ(n log a 5 ) Veja AU, sec 3.11, p.151 A mesma coisa, escrita de maneira um pouco diferente (Master Theorem, CLRS, sec. 4.3, p.73): Suponha T(n) = at(n/5) + f(n) para algum a 1. Então, em geral, se f(n) = O(n log a ǫ 5 ) então T(n) = Θ(n log a 5 ) se f(n) = Θ(n log a 5 ) então T(n) = Θ(n log a 5 lg n) se f(n) = Ω(n log a+ǫ 5 ) então T(n) = Θ(f(n)) para qquer ǫ > 0 No lugar de n/5, posso escrever n/5 ou n/5 5, posso escrever qualquer b > 1 4, posso escrever qualquer número real 4n 3 posso escrever qualquer polinômio de grau 3 3, posso escrever qualquer inteiro k 0 6, posso escrever qualquer número a > 1 55
TAREFA 9 Exercício 9.A A que classe O pertencem as solução de recorrência do tipo T(n) = T(n/3) + O(1)? Exercício 9.Aa Seja T a função definida pela recorrência T(1) = 1 T(n) = 4T( n/2 ) + n para n = 2,3,4,5,... A que ordem Θ pertence T? Exercício 9.B [CLRS 4.2-1] Seja T a função definida pela recorrência T(1) = 1 T(n) = 3T( n/2 ) + n para n = 2,3,4,5,... A partir da árvore da recorrência, adivinhe a que classe Θ pertence T(n). Prove a cota pelo método da substituição. Exercício 9.C Resolva a recorrência T(1) = 1 T(n) = 2T( n/2 ) + 7n + 2 para n = 2,3,4,5,... Exercício 9.D Resolva a recorrência T(n) = T(n 2) + O(n). Exercício 9.E Resolva a recorrência T(n) = 5T(n 1) + O(n). 56
AULA 10 Análise de algoritmos recursivos CLRS 2.3 AU 2.8, 3.9, 3.10 57
Exemplo 1: Ordenação por inserção Rearranja A[p.. r], com p r, em ordem crescente ORDENA-POR-INS (A, p, r) 1 se p < r 2 então ORDENA-POR-INS(A, p, r 1) 3 chave A[r] 4 i r 1 5 enquanto i p e A[i] > chave faça 6 A[i + 1] A[i] 7 i i 1 8 A[i + 1] chave O algoritmo está correto? T(n) := consumo de tempo máximo quando r p + 1 = n linha consumo na linha 1 O(1) 2 T(n 1) 3 O(1) 4 O(1) 5 O(n) 6 O(n) 7 O(n) 8 O(1) T(n) = T(n 1) + O(3n + 4) 58
T(n) = T(n 1) + O(n) Tradução: existe fção F(n) em O(n) tq T(n) = T(n 1) + F(n) para todo n suficientemente grande Mais tradução: Existem a, c > 0 e n 0 > 0 tq T(n 0 1) = a e T(n) T(n 1) + cn para todo n n 0 (em virtude do ex 3.I poderíamos tomar n 0 = 0) Solução: T(n) = O(n 2 ) Prova? Exemplo: T(1) = 1 T(n) = T(n 1) + 3n + 4 para n 2 Solução: T(n) 4n 2 para n 1 Prova? 59
Exemplo 2: Merge-Sort Rearranja A[p.. r], com p r, em ordem crescente. MERGE-SORT (A, p, r) 1 se p < r 2 então q (p + r)/2 3 MERGE-SORT(A, p, q) 4 MERGE-SORT(A, q + 1, r) 5 INTERCALA(A, p, q, r) p q r 99 99 99 99 99 99 99 99 99 O algoritmo está correto? T(n) := consumo de tempo máximo quando r p + 1 = n linha consumo na linha 1 O(1) 2 O(1) 3 T( n/2 ) 4 T( n/2 ) 5 O(n) T(n) = T( n/2 ) + T( n/2 ) + O(n + 2) 60
T(n) = T( n/2 ) + T( n/2 ) + O(n) Solução: T(n) = O(nlg n). Prova? 61
AULA 11 Heapsort CLRS 6 (veja tb CLRS B.5.3) 62
Heap sort Rearranja A[1.. n] em ordem crescente. HEAPSORT (A, n) 1 BUILD-MAX-HEAP(A, n) 2 para m n decrescendo até 2 3 faça A[1] A[m] 4 MAX-HEAPIFY(A, m 1, 1) 1 m n 66 44 55 44 22 33 11 77 88 99 99 Invariante: no início de cada execução de 2 4, A[m+1.. n] grandes, ordem crescente A[1.. m] pequenos, max-heap 63
Estrutura de heap 01 02 03 04 05 06 07 08 09 10 11 12 13 14 16 17 18 19 20 21 22 23 24 25 26 A[1..29] filho esquerdo de i 2i filho direito de i 2i + 1 pai de i i/2 nível de i lg i (nível p tem 2 p nós) altura de i lg m i raiz (i = 1) nível = 0 folha altura = 0 A[1.. m] é um max-heap se A[ i 2 ] A[i] para cada nó i. 64
Exercício 11.A CLRS 6.1-2 A altura de i em A[1.. m] é o comprimento da mais longa seqüência da forma f(i), f(f(i)), f(f(f(i))),..., onde f(i) vale 2i ou 2i + 1. Mostre que a altura de i é lg m i 65
Exercício 11.B CLRS 6.3-3 Mostre que um heap A[1.. m] tem no máximo m/2 h+1 nós com altura h. EXEMPLO: N h = número de nós à altura h m m/2 N 0 m/2 m/4 N 1 m/4 16 8 8 8 4 4 4 17 8 9 9 4 4 5 18 9 9 9 4 5 5 19 9 10 10 4 5 5 20 10 10 10 5 5 5 21 10 11 11 5 5 6 22 11 11 11 5 6 6 23 11 12 12 5 6 6 24 12 12 12 6 6 6 66
Exercício 11.C Mostre que m/2 h+1 m/2 h quando h lg m. 67
Rotina básica de manipulação de max-heap MAX-HEAPIFY (A, m, i) 01 l 2i 02 r 2i + 1 03 se l m e A[l] > A[i] 04 então maior l 05 senão maior i 06 se r m e A[r] > A[maior] 07 então maior r 08 se maior i 09 então A[i] A[maior] 10 MAX-HEAPIFY(A, m, maior) Recebe A[1.. m] e i 1 tais que subárvores com raiz 2i e 2i + 1 são max-heaps. Rearranja de modo que subárvore com raiz i seja max-heap. h := altura de i = lg m i T(h) := consumo de tempo no pior caso 68
Recorrência: T(h) = T(h 1) + O(1) pois altura de maior é h 1 Solução: T(h) = O(h) Prova? Como h lg m, podemos dizer que consumo de tempo de MAX-HEAPIFY(A, m, i) é O(lg m) 69
Construção de um max-heap BUILD-MAX-HEAP (A, n) 2 para i n/2 decrescendo até 1 3 faça MAX-HEAPIFY(A, n, i) T(n) := consumo de tempo no pior caso T(n) = n 2 O(lg n) = O(nlg n). Análise mais cuidadosa: T(n) = O(n). PROVA: Digamos que MAX-HEAPIFY(A, n, i) consome h = lg n i unidades de tempo. Então 70
T(n) = lg n h=1 n 2 h+1 h lg n h=1 n 2 h h n ( 1 2 1 + 2 2 2 + 3 lg n + + 23 2 lg n < n = 2n 1/2 (1 1/2) 2 ) Comentário: x 0 + x 1 + x 2 + x 3 + = 1 1 x 1x 0 + 2x 1 + 3x 2 1 + = (1 x) 2 1x 1 + 2x 2 + 3x 3 x + = (1 x) 2 71
Consumo de tempo do Heap sort HEAPSORT (A, n) 1 BUILD-MAX-HEAP(A, n) 2 para m n decrescendo até 2 3 faça A[1] A[m] 4 MAX-HEAPIFY(A, m 1,1) linha consumo na linha 1 O(n) 2 O(n) 3 O(n) 4 no(lg n) Total:O(n lg n) 72
AULA 12 Filas com prioridades CLRS 6.5 73
Filas com prioridade Tipo abstrato de dados (= abstract data type) A 1 m Como organizar A[1.. m] de modo que as operações consulte máximo extraia máximo aumenta valor de elemento insira novo elemento sejam eficientes? Vetor sem ordem alguma? crescente? decrescente? Implementações com max-heap: HEAP-MAX (A, m) 1 devolva A[1] Consome O(1) 74
HEAP-EXTRACT-MAX (A, m) m 1 3 max A[1] 4 A[1] A[m] 5 m m 1 6 MAX-HEAPIFY (A, m, 1) 7 devolva max HEAP-INCREASE-KEY (A, i, chave) chave A[i] 3 A[i] chave 4 enquanto i > 1 e A[ i/2 ] < A[i] 5 faça A[i] A[ i/2 ] 6 i i/2 MAX-HEAP-INSERT (A, m, chave) 1 m m + 1 2 A[m] 3 HEAP-INCREASE-KEY (A, m, chave) Todos consomem O(lg m) 75
AULA 13 Exercício relevante para o Quicksort 76
Exercício 13.A T(1) = 1 T(n) = T( n/3 ) + T( 2n/3 ) + 5n para n = 2,3,4,... Faz sentido? Solução?? T(n) = O(??) Para adivinhar a cara da solução, vou tentar uma recorrência mais simples: T(1) = 1 T(n) = T(n/3) + T(2n/3) + 5n para n = 2,3,4,... Mas isso não faz sentido! Então que tal essa: T(x) = 1 para x racional tq 3 1 < x 1 T(x) = T(x/3) + T(2x/3) + 5x para x racional, x > 1. 77
Árvore da recorrência: 5n / \ 5 n 3 5 2n 3 / \ / \ 5 n 9 5 2n 9 5 2n 9 5 4n 9 \ / \ / \ 5 4n 5 4n 5 8n 9 27 27. soma em cada horizontal = 5n número de níveis log 3/2 n T(n) = a soma de tudo T(n) 5n log 3/2 n + 1 + + 1 }{{} log 3/2 n T(n) = O(nlg n) 78
De volta à recorrência: T(1) = 1 e T(n) = T( n/3 ) + T( 2n/3 ) + 5n para n = 2,3,4,... n T(n) 1 1 2 1 + 1 + 5 2 = 12 3 1 + 12 + 5 3 = 28 4 12 + 12 + 5 4 = 44 Vou mostrar que T(n) 100 nlg n para n = 2,3,4,5,6,... Prova: Para n = 2 temos T(2) = 12 < 100 2 lg2. Para n = 3 temos T(3) = 28 < 100 3 lg3. Suponha agora que n > 3. Então 79
T(n) = T( n 3 ) + T( 2n 3 ) + 5n hi 100 n 3 lg n 3 + 100 2n 3 lg 2n 3 + 5n 100 n + 2 3 < 100 n + 2 3 = 100 n + 2 3 lg n 3 + 1002n 3 lg 2n 3 + 5n (lg n 3 + 1) + 1002n 3 lg 2n 3 + 5n lg 2n 3 + 1002n 3 lg 2n 3 + 5n = 100 n 3 lg 2n 3 + 1002 3 lg 2n 3 + 1002n 3 lg 2n 3 + 5n < 100nlg 2n 3 + 67lg 2n 3 + 5n = 100nlg n + 100nlg 2 3 + 67lg n + 67lg 2 3 + 5n < 100nlg n + 100n( 0.58) + 67lg n + 67( 0.58) + 5n < 100nlg n 58n + 67lg n 38 + 5n = 100nlg n 53n + 67lg n 38 < 100nlg n Bingo! 80
AULA 14 Quicksort CLRS 7 81
Quicksort Rearranja A[p.. r] em ordem crescente. QUICKSORT (A, p, r) 1 se p < r 2 então q PARTICIONE(A, p, r) 3 QUICKSORT(A, p, q 1) 4 QUICKSORT(A, q + 1, r) p q r 22 22 22 11 11 44 88 99 88 99 88 No começo da linha 3, A[p.. q 1] A[q] A[q+1.. r] 82
PARTICIONE rearranja A de modo que p q r e A[p.. q 1] A[q] A[q+1.. r] PARTICIONE (A, p, r) 1 x A[r] x é o pivô 2 i p 1 3 para j p até r 1 4 faça se A[j] x 5 então i i + 1 6 A[i] A[j] 7 A[i + 1] A[r] 8 devolva i + 1 Invariantes: no começo de cada iteração de 3 6, A[p.. i] x A[i+1.. j 1] > x A[r] = x p i j r 22 22 22 88 88 88 11 99 11 99 44 Consumo de tempo de PARTICIONE é Θ(n), sendo n = r p + 1. 83
Consumo de tempo do Quicksort QUICKSORT (A, p, r) 1 se p < r 2 então q PARTICIONE(A, p, r) 3 QUICKSORT(A, p, q 1) 4 QUICKSORT(A, q + 1, r) T(n) := consumo de tempo no pior caso sendo n := r p + 1 Recorrência grosseira: T(n) = T(0) + T(n 1) + Θ(n) Solução: T(n) = Θ(n 2 ) Recorrência cuidadosa: T(n) = { } max T(k) + T(n k 1) + Θ(n) 0 k n 1 Solução: T(n) = Θ(n 2 ) Prova? 84
EXEMPLO CONCRETO: S(0) = S(1) = 1 e { } S(n) = S(k) + S(n k 1) + n para n 2. max 0 k n 1 n S(n) 0 1 1 1 2 2 + 2 3 5 + 3 4 9 + 4 Vou provar que S(n) n 2 + 1 para n 0. Prova: Trivial para n 1. Se n 2 então S(n) = hi max 0 k n 1 max 0 k n 1 { S(k) + S(n k 1) } + n { k 2 + 1 + (n k 1) 2 + 1 } + n = (n 1) 2 + 2 + n exerc 14.E = n 2 n + 3 n 2 + 1. Prove que S(n) 1 2 n2 para n 1. 85
Tempo do QUICKSORT no melhor caso: n 1 R(n) = R( ) + R( 2 n 1 2 ) + Θ(n) Solução: R(n) = Θ(nlg n) 86
TAREFA 14 Exercício 14.A Submeta ao algoritmo PARTICIONE um vetor com n elementos iguais. Como o algoritmo permuta o vetor recebido? Quantas trocas faz (linhas 6 e 7) entre elementos do vetor? Exercício 14.B [CLRS 7.2-2] Qual o consumo de tempo do QUICKSORT quando aplicado a um vetor com n elementos iguais? Exercício 14.C [CLRS 7.2-3] Mostre que o consumo de tempo do QUICKSORT é Ω(n 2 ) quando aplicado a um vetor crescente com n elementos distintos. Exercício 14.D [CLRS 7.4-1, modificado] Seja S a função definida sobre os inteiros positivos pela seguinte recorrência: S(0) = S(1) = 1 e S(n) = max {S(k) + S(n k 1)} + n 0 k n 1 quando n 2. Mostre que S(n) 1 2 n2 para n 1. Exercício 14.E [CLRS 7.4-3] Mostre que k 2 + (n k 1) 2 atinge o máximo para 0 k n 1 quando k = 0 ou k = n 1. Exercício 14.F É verdade que 2 2n/3 /3 = 4n/9? É verdade que 2 2n/3 /3 = 4n/9? Exercício 14.G [CLRS 7-4] Considere a seguinte variante do algoritmo Quicksort: QUICKSORT (A, p, r) enquanto p < r faça q PARTICIONE(A, p, r) QUICKSORT (A, p, q 1) p q + 1 Mostre que a pilha de recursão pode atingir altura proporcional a n, onde n := r p + 1. Modifique o código de modo que a pilha de recursão tenha altura O(lg n). (Veja enunciado completo em CLRS p.162.) 87
AULA 15 Consumo médio de tempo do Quicksort CLRS 7.4 88
Quicksort Consumo de tempo no pior caso: Θ(n 2 ) No melhor caso: Θ(n lg n) Consumo médio? Divisão 1 3 para 2 3 : R(n) = R( n 1 3 ) + R( 2n 2 3 ) + Θ(n) Solução: R(n) = Θ(n lg n) veja exercício 13.A Divisão 1 10 para 9 10 : R(n) = R( n 1 10 ) + R( 9n 9 10 Solução: R(n) = Θ(nlg n) ) + Θ(n) Isso sugere que consumo médio é Θ(nlg n). Confirmação? 89
EXEMPLO: Número médio de execuções da linha 4 do PARTICIONE. Suponha que A[p.. r] é permutação de 1.. n A[p.. r] execs 1,2 1 2,1 1 média 1 A[p.. r] execs 1,2,3 2+1 2,1,3 2+1 1,3,2 2+0 3,1,2 2+0 2,3,1 2+1 3,2,1 2+1 média 16/6 A[p.. r] execs 1,2,3,4 3+3 2,1,3,4 3+3 1,3,2,4 3+2 3,1,2,4 3+2 2,3,1,4 3+3 3,2,1,4 3+3 1,2,4,3 3+1 2,1,4,3 3+1 1,4,2,3 3+1 4,1,2,3 3+1 2,4,1,3 3+1 4,2,1,3 3+1 A[p.. r] execs 1,3,4,2 3+1 3,1,4,2 3+1 1,4,3,2 3+1 4,1,3,2 3+1 3,4,1,2 3+1 4,3,1,2 3+1 2,3,4,1 3+3 3,2,4,1 3+3 2,4,3,1 3+2 4,2,3,1 3+2 3,4,2,1 3+3 4,3,2,1 3+3 média 116/24 O número médio coincide exatamente com a fórmula E[X] = n 1 a=1 dada algumas transparência adiante. n a k=1 2 k+1 90
Algo melhor: Quicksort aleatorizado PARTICIONE-ALEA (A, p, r) 1 i RANDOM(p, r) 2 A[i] A[r] 3 devolva PARTICIONE(A, p, r) QUICKSORT-ALE (A, p, r) 1 se p < r 2 então q PARTICIONE-ALEA(A, p, r) 3 QUICKSORT-ALE(A, p, q 1) 4 QUICKSORT-ALE(A, q + 1, r) Análise do consumo medio? Basta contar o número esperado de comparações na linha 4 do PARTICIONE 91
Suponha A[p.. r] permutação de 1.. n Quero calcular X = total de comparaçs A[j] x = n 1 n X ab a=1 b=a+1 X ab = número de comparações entre a e b EXEMPLO: 1 3 6 2 5 7 4 1 3 2 4 5 7 6 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 1 0 1 0 0 0 2 1 1 1 0 0 0 3 0 1 1 0 0 0 4 1 1 1 1 1 1 5 0 0 0 1 1 0 6 0 0 0 1 1 1 7 0 0 0 1 0 1 92
Supondo a < b, X ab = 1 se primeiro pivô em {a,..., b} é a ou b 0 caso contrário Pr {X ab =1} = 1 b a + 1 + 1 b a + 1 X = n 1 n X ab a=1 b=a+1 E[X] =? 93
E[X] = = n 1 n a=1 b=a+1 n 1 n a=1 b=a+1 E[X ab ] Pr {X ab =1} = n 1 n a=1 b=a+1 2 b a + 1 = n 1 n a a=1 k=1 2 k + 1 < n 1 a=1 2( 1 1 + 1 2 + + 1 n ) < 2n( 1 1 + 1 2 + + 1 n ) < 2n(ln n + 1) CLRS (A.7), p.1060 Consumo esperado do QUICKSORT-ALE: O(nlg n) 94
AULA 16 E por falar em análise probabilística e algoritmos aleatorizados... CLRS 5 e C.2 C.3 95
Hiring problem: Encontrar o máximo de permutação A[1.. n] de 1,..., n MAX (A, n) 1 max 0 2 para i 1 até n 3 faça se A[i] > max 4 então max A[i] 5 devolva max Quantas vezes linha 4 é executada? Melhor caso, pior caso, caso médio Suponha que A[1.. n] é permutação aleatória uniforme de 1,..., n isto é, cada permutação tem probabilidade 1/n! 96
EXEMPLO: número de execuções da linha 4 A[1..2] linha 14 1,2 2 2,1 1 E[X] 3/2 A[1..4] linha 14 1,2,3,4 4 1,2,4,3 3 1,3,2,4 3 1,3,4,2 3 1,4,2,3 2 1,4,3,2 2 2,1,3,4 3 2,1,4,3 2 2,3,1,4 3 2,3,4,1 3 2,4,1,3 2 2,4,3,1 2 A[1..3] linha 14 1,2,3 3 1,3,2 2 2,1,3 2 2,3,1 2 3,1,2 1 3,2,1 1 E[X] 11/6 A[1..4] linha 14 3,1,2,4 2 3,1,4,2 2 3,2,1,4 2 3,2,4,1 2 3,4,1,2 2 3,4,2,1 2 4,1,2,3 1 4,1,3,2 1 4,2,1,3 1 4,2,3,1 1 4,3,1,2 1 4,3,2,1 1 E[X] 50/24 97
Variáveis aleatórias: X i = 1 se max A[i] é executado 0 caso contrário X = núm total de execs da linha 4 = X 1 + + X n Esperanças: E[X i ] = probabilidade de que A[i] seja máximo em A[1.. i] = 1/i E[X] = E[X 1 + + X n ] = E[X 1 ] + + E[X n ] = 1/1 + + 1/n < ln n + 1 = O(lg n) 2.92 < 1 1 + + 1 10 < 2.93 < 3.30 < 1 + ln10 98
Como garantir permutação aleatória uniforme? MAX-ALEATORIZADO (A, n) 0 PERMUTE(A) 1 max 0 2 para i 1 até n 3 faça se A[i] > max 4 então max A[i] 5 devolva max Linha 0 faz uma permutação aleatória uniforme dos elementos de A Como? 99
Solução 1 PERMUTE-POR-ORDENAÇÃO (A, n) 1 para i 1 até n faça 2 P[i] RANDOM(1, n 3 ) 3 ordene A[1.. n] com chaves P[1.. n] No começo da linha 3, com grande probabilidade, P[1.. n] não tem elementos repetidos Linha 3 faz permutação A[j 1.. j n ] de A[1.. n] tal que P[j 1 ] P[j n ] Consumo de tempo: Θ(n lg n) se RANDOM for Θ(1) 100
Solução 2 (Como se diz in place em portugues?) PERMUTE-IN-PLACE (A, n) 1 para i 1 até n faça 2 j RANDOM(i, n) 3 A[j] A[i] Não é óbvio que isso produz permutação aleatória uniforme de A[1.. n] Consumo de tempo: Θ(n) supondo que RANDOM é Θ(1) 101
TAREFA 16 Exercício 16.A [CLRS 5.3-3] Que acontece se trocarmos RANDOM(i, n) por RANDOM(1, n) no algoritmo PERMUTE-IN-PLACE? O algoritmo continua produzindo permutação aleatória uniforme? Exercício 16.B [CLRS C.3-2] Um vetor A[1.. n] contém n números distintos aleatoriamente ordenados. Suponha que cada permutação dos n números é igualmente provável. Qual é a esperança do índice do maior elemento do vetor? Qual é a esperança do índice do menor elemento do vetor? 102
AULA 17 Limite inferior para o problema da ordenação CLRS 8.1 103
Ordenação: limite inferior Problema: Rearranjar A[1... n] em ordem crescente Existem algoritmos O(n lg n) Existe algoritmo assintoticamente melhor? NÃO, se o algoritmo é baseado em comparações Prova? Qualquer algoritmo de comparações é uma árvore de decisão 104
EXEMPLO: INSERTION-SORT com n = 3 Árvore de decisão para a, b, c, todos distintos a : b representa comparação entre a e b a : b < > b : c a : c / \ / \ abc a : c bac b : c / \ / \ acb cab bca cba bac significa que b < a < c 105
Árvore de decisão para A[1.. n] todas as n! permutações de 1,..., n devem ser folhas número de comparações, no pior caso? resposta: altura, h, da árvore devemos ter 2 h n!, donde h lg(n!) (n!) 2 = n 1 i=0 (n i)(i+1) n i=1 n = n n h lg(n!) 1 2 nlg n Conclusão: Todo algoritmo de ordenação baseado em comparações faz Ω(nlg n) comparações no pior caso 106
AULA 18 Ordenação em tempo linear CLRS 8.2 8.3 107
Ordenação por contagem Cada A[i] está em {0,..., k} COUNTING-SORT (A, B, n, k) 1 para i 0 até k 2 faça C[i] 0 3 para j 1 até n 4 faça C[A[j]] C[A[j]] + 1 5 para i 1 até k 6 faça C[i] C[i] + C[i 1] 7 para j n decrescendo até 1 8 faça B[C[A[j]]] A[j] 9 C[A[j]] C[A[j]] 1 A 1 n B C 0 k Entre linhas 4 e 5, C[i] = núm de js tq A[j] = i entre linhas 6 e 7, C[i] = núm de js tq A[j] i 108
Consumo de tempo do COUNTING-SORT: linha consumo na linha 1 2 Θ(k) 3 4 Θ(n) 5 6 Θ(k) 7 9 Θ(n) Consumo total: Θ(n + k) se k n então consumo é Θ(n) se k 10n então consumo é Θ(n) se k = O(n) então consumo é Θ(n) se k n 2 então consumo é Θ(k) A propósito: COUNTING-SORT é estável 109
Ordenação digital (= radix sort) Exemplo: 329 720 720 329 457 355 329 355 657 436 436 436 839 457 839 457 436 657 355 657 720 329 457 720 355 839 657 839 Cada A[j] têm d dígitos decimais: A[j] = a d 10 d 1 + + a 2 10 1 + a 1 10 0 Exemplo com d = 3: 3 10 2 + 2 10 + 9 RADIX-SORT (A, n, d) 1 para i 1 até d faça 2 1 até d e não o contrário! 3 ordene A[1.. n] pelo dígito i 110
Linha 3: faz ordenação A[j 1.. j n ] de A[1.. n] tal que A[j 1 ] i A[j n ] i ordenação deve ser estável use COUNTING-SORT Consumo de tempo: dígitos decimais: dígitos em 0.. k: Θ(dn) Θ(d(n + k)). Exemplo com d = 5 e k = 128: a 5 128 4 + a 4 128 3 + a 3 128 2 + a 2 128 + a 1 sendo 0 a i 127 111
AULA 19 Mediana e i-ésimo menor elemento CLRS 9 112
Mínimo e mediana Problema: Encontrar o i-ésimo menor elemento de A[1.. n] Suponha A[1.. n] sem elementos repetidos Exemplo: 33 é o 4-o menor elemento: 22 99 32 88 34 33 11 97 55 66 A 11 22 32 33 34 55 66 88 97 99 ordenado Mediana é o n+1 2 -ésimo menor ou o n+1 2 -ésimo menor elemento 113
Algoritmo SELECT Recebe A[p.. r] e i tal que 1 i r p+1 e devolve valor do i-ésimo menor elemento de A[p.. r] SELECT (A, p, r, i) 1 se p = r 2 então devolva A[p] 3 q PARTICIONE(A, p, r) 4 k q p + 1 5 se k = i 6 então devolva A[q] 7 se k > i 8 então devolva SELECT (A, p, q 1, i) 9 senão devolva SELECT (A, q + 1, r, i k) p q r } {{ } } {{ } k 1 n k 114
T(n) = núm comparações entre elementos de A quando n = r p + 1 Pior caso: T(n) = T(n 1) + n 1 Solução: T(n) = Θ(n 2 ) T(1) = 0 e T(n) = T(n 1) + n 1 para n 2 Solução: T(n) = 1 2 n2 1 2 n Consumo médio? E[T(n)] =? 115
EXEMPLO: Número médio de comparações sobre todas as permutações de A[p.. r] (supondo que nas linhas 8 e 9 o algoritmo sempre escolhe o lado maior): A[p.. r] comps 1,2 1+0 2,1 1+0 média 2/2 A[p.. r] comps 1,2,3 2+1 2,1,3 2+1 1,3,2 2+0 3,1,2 2+0 2,3,1 2+1 3,2,1 2+1 média 16/6 A[p.. r] comps 1,2,3,4 3+3 2,1,3,4 3+3 1,3,2,4 3+2 3,1,2,4 3+2 2,3,1,4 3+3 3,2,1,4 3+3 1,2,4,3 3+1 2,1,4,3 3+1 1,4,2,3 3+1 4,1,2,3 3+1 2,4,1,3 3+1 4,2,1,3 3+1 A[p.. r] comps 1,3,4,2 3+1 3,1,4,2 3+1 1,4,3,2 3+1 4,1,3,2 3+1 3,4,1,2 3+1 4,3,1,2 3+1 2,3,4,1 3+3 3,2,4,1 3+3 2,4,3,1 3+2 4,2,3,1 3+2 3,4,2,1 3+3 4,3,2,1 3+3 média 116/24 No caso r p + 1 = 5, a média é 864/120. 116
SELECT-ALEATORIZADO (= randomized select) Usa PARTICIONE-ALEATORIZADO Consumo médio de tempo: E[T(1)] = 0 e E[T(n)] n 1 + 1 n n 1 h=ae[t(h)]+ 1 n n 1 h=b E[T(h)] onde a = n/2 e b = n/2 Compare com a recorrência do Quicksort n E[T(n)] = 1 0 0 2 2/2 1 3 16/6 2.7 4 116/24 4.8 5 864/120 7.2 Solução: E[T(n)] = O(n) 117
AULA 20 Programação dinâmica CLRS 15.1 15.3 118
Programacão dinâmica = recursão com tabela = transformação inteligente de recursão em iteração EXEMPLO 1: Números de Fibonacci F 0 = 0 F 1 = 1 F n = F n 1 + F n 2 Algoritmo recursivo para F n : FIBO-REC (n) 1 se n 1 2 então devolva n 3 senão a FIBO-REC(n 1) 4 b FIBO-REC(n 2) 5 devolva a + b Consumo de tempo? Número de somas: T(0) = 0 T(1) = 0 T(n) = T(n 1) + T(n 2) + 1 se n 2 119
Solução: T(n) 3 n /2 n para n 6. Prova: T(6) = 12 > (3/2) 6 e T(7) = 20 > (3/2) 7. Se n 8 então T(n) = T(n 1) + T(n 2) + 1 (3/2) n 1 + (3/2) n 2 + 1 = (3/2 + 1)(3/2) n 2 + 1 (5/2)(3/2) n 2 (9/4)(3/2) n 2 = (3/2) 2 (3/2) n 2 = (3/2) n. Consumo de tempo: Ω(( 3 2 )n ) Exponencial! Algoritmo resolve as mesmas subinstâncias muitas vezes: F 5 / \ F 4 F 3 / \ / \ F 3 F 2 F 2 F 1 / \ / \ / \ F 2 F 1 F 1 F 0 F 1 F 0 120
Algoritmo de programação dinâmica: FIBO (n) 1 f[0] 0 2 f[1] 1 3 para i 2 até n 4 faça f[i] f[i 1] + f[i 2] 5 devolva f[n] Note a tabela f[0.. n 1] Consumo de tempo: Θ(n) 121
Programacão dinâmica, EXEMPLO 2: Subset-sum (soma de cheques) Dados inteiros não-negativos w 1,..., w n, W, encontrar subconjunto K de {1,..., n} tal que k K w k = W. Exemplo w = 100,30,90,35,40,30,10 e W = 160 Motivação: Algum subconjunto dos cheques w 1,..., w n (w i é o valor do cheque i) tem soma W? Propriedade da subestrutura ótima: Suponha que K é solução da instância (n, W) do problema. Se K n então K {n} é solução da instância (n 1, W w n ) senão K é solução da instância (n 1, W). 122
Simplificação: diga 1 se a instância tem solução e 0 em caso contrário. Solução recursiva: REC (w, n, W) 1 se W = 0 2 então devolva 1 3 se n = 0 4 então devolva 0 5 se REC(w, n 1, W) = 1 6 então devolva 1 7 se w n > W 8 então devolva 0 9 senão devolva REC(w, n 1, W w n ) Consumo de tempo: Ω(2 n ) Por que demora tanto? A mesmo instância é resolvida muitas vezes. 123
Programação dinâmica s[i, Y ] := 1 se instância (i, Y ) tem solução 0 caso contrário Recorrência: s[i,0] = 1 s[0, Y ] = 0 se Y > 0 s[i, Y ] = s[i 1, Y ] se w i > Y s[i, Y ] = max {s[i 1, Y ], s[i 1, Y w i } Y 0 1 2 3 4 i 0 0 0 0 0 0 1 2 3 4? 5 W = 4 n = 5 Lembrete: W e w 1,..., w n são inteiros 124
Cada instâcia (i, Y ) do problema é resolvida uma só vez: SOMA-DE-SUBCONJ (w, n, W) 1 para i 0 até n faça 2 s[i,0] 1 3 para Y 1 até W faça 4 s[0, Y ] 0 5 para i 1 até n faça 6 s[i, Y ] s[i 1, Y ] 7 se s[i, Y ] = 0 e w i Y 8 então s[i, Y ] s[i 1, Y w i ] 9 devolva s[n, W] Consumo de tempo: Θ(nW) NOTA: O consumo Θ(n2 lg W ) é exponencial! Explicação: o tamanho de W é lg W e não W (tente multiplicar w 1,..., w n e W por 1000) EXERCÍCIO: Escreva uma versão que devolva K tal que k K w k = W 125
Programacão dinâmica, EXEMPLO 3: Multiplicação iterada de matrizes Preliminares: Se A é p q e B é q r então AB é p r (AB)[i, j] = k A[i, k] B[k, j] Número de multiplicações escalares = p q r MULT-MAT (p, A, q, B, r) 1 para i 1 até p faça 2 para j 1 até r faça 3 AB[i, j] 0 4 para k 1 até q faça 5 AB[i, j] AB[i, j] + A[i, k] B[k, j] Multiplicação iterada: A 1 A 2 A 3 10 A 1 100 A 2 5 A 3 50 ((A 1 A 2 ) A 3 ) 7500 mults escalares (A 1 (A 2 A 3 )) 75000 mults escalares 126
Problema: Encontrar número mínimo de multiplicações escalares necessário para calcular produto A 1 A 2 A n. p 0 p 1 p 2... p n 1 p n A 1 A 2... A n cada A i é p i 1 p i Soluções ótimas contêm soluções ótimas: se (A 1 A 2 )(A 3 ((A 4 A 5 )A 6 )) é ordem ótima de multiplicação então (A 1 A 2 ) e (A 3 ((A 4 A 5 )A 6 )) também são ordens ótimas. 127
m[i, j] = número mínimo de multiplicações escalares para calcular A i A j Decomposição: (A i A k )(A k+1 A j ) Recorrência: se i = j então m[i, j] = 0 se i < j então m[i, j] = min i k<j { m[i, k] + p i 1 p k p j + m[k+1, j] } Exemplo: m[3,7] = min 3 k<7 { m[3, k] + p 2p k p 7 + m[k+1,7] } 128
Algoritmo recursivo: recebe p i 1,..., p j e devolve m[i, j] REC-MAT-CHAIN (p, i, j) 1 se i = j 2 então devolva 0 3 m[i, j] 4 para k i até j 1 faça 5 q 1 REC-MAT-CHAIN (p, i, k) 5 q 2 REC-MAT-CHAIN (p, k + 1, j) 5 q q 1 + p i 1 p k p j + q 2 6 se q < m[i, j] 7 então m[i, j] q 8 devolva m[i, j] Consumo de tempo: Ω(2 n ) onde n = j i + 1. Por que demora tanto? Uma mesma instância é resolvida muitas vezes. 129
Cálculo do consumo de tempo de REC-MAT-CHAIN: T(n) = número comparações entre q e m[, ] na linha 6 quando n := j i + 1 para n 2 T(1) = 0 T(n) = n 1 k=1 n 1 = 2 k=2 (T(k) + T(n k) + 1) T(h) + (n 1) = 2(T(2) + + T(n 1)) + (n 1) Fácil verificar: T(n) 2 n 2 para n 2 130
Programação dinâmica: cada instância A i A j resolvida uma só vez. Em que ordem calcular os componentes da tabela m? Para calcular m[2, 6] preciso de m[2,2], m[2,3], m[2,4], m[2,5] e de m[3,6], m[4,6], m[5,6], m[6,6]. 1 2 3 4 5 6 7 8 j 1 0 2 0? 3 0 4 0 5 0 6 0 7 0 8 0 i Calcule todos os m[i, j] com j i + 1 = 2, depois todos com j i + 1 = 3, depois todos com j i + 1 = 4, etc. 131
Algoritmo de programação dinâmica: recebe p 0, p 1,..., p n e devolve m[1, n] MATRIX-CHAIN-ORDER (p, n) 02 para i 1 até n faça 03 m[i, i] 0 04 para l 2 até n faça 05 para i 1 até n l + 1 faça 06 j i + l 1 07 m[i, j] 08 para k i até j 1 faça 09 q m[i, k] + p i 1 p k p j + m[k+1, j] 10 se q < m[i, j] 11 então m[i, j] q 12 devolva m[1, n] Linhas 4 11: tratam das subcadeias A i A j de comprimento l Consumo de tempo: O(n 3 ) 132
Curioso verificar que consumo é Ω(n 3 ): Número de execuções da linha 9 (para cada i, linha 9 é executada l 1 vezes) l i execs linha 9 2 1,..., n 1 (n 1) 1 3 1,.., n 2 (n 2) 2 4 1,., n 3 (n 3) 3 n 1 1,2 2 (n 2) n 1 1 (n 1) total n 1 h=1 h(n h) Para n 6, n 1 h=1 h(n h) = = n n 1 h=1 h n 1 h=1 h2 = n 1 2 n(n 1) 1 (n 1)n(2n 1) (CLRS p.1060) 6 1 2 n2 (n 1) 1 6 2n3 1 2 n25n 6 1 3 n3 = 5 12 n3 1 3 n3 = 1 12 n3 Consumo de tempo é Ω(n 3 ) 133
AULA 21 Mais programação dinâmica CLRS 15.4 134
Def: z 1,..., z k é subseqüência de x 1,..., x m se existem índices i 1 < < i k tais que z 1 = x i1... z k = x ik EXEMPLO: 5, 9, 2, 7 é subseqüência de 9,5,6,9,6,2,7,3 135
Pequeno exercício: Decidir se z 1,..., z k é subseqüência de x 1,..., x m Exemplo: z = A A A x = B A B B A B B B A A B B A B A B A B B Solução: SUB-SEQ- (z, k, x, m) 0 i k 1 j m 2 enquanto i 1 e j 1 faça 3 se z i = x j 4 então i i 1 5 j j 1 6 se i 1 7 então devolva não 8 senão devolva sim 136
Programacão dinâmica, EXEMPLO 4: Subseqüência comum máxima Z é subseq comum de X e Y se Z é subseq de X e de Y ssco = subseq comum Problema: Encontrar uma ssco máxima de X e Y Exemplo: X = A B C B D A B Y = B D C A B A ssco = B C A ssco maximal = A B A ssco máxima = B C A B Outra ssco máxima = B D A B LCS = longest common subsequence 137
Subestrutura ótima: Suponha que Z = z 1,..., z k é sscomáx de X = x 1,..., x m e Y = y 1,..., y n. Se x m = y n então z k = x m = y n e Z k 1 é sscomáx de X m 1 e Y n 1 Se x m y n então z k x m implica que Z é sscomáx de X m 1 e Y Se x m y n então z k y n implica que Z é sscomáx de X e Y n 1 Notação: X j := x 1,..., x j Prove a propriedade! 138
Simplificação: encontrar o comprimento de uma ssco máxima c[i, j] = comprimento de uma sscomáx de x 1,..., x i e y 1,..., y j Recorrência: c[0, j] = c[i,0] = 0 c[i, j] = c[i 1, j 1] + 1 se x i = y j c[i, j] = max(c[i, j 1], c[i 1, j]) se x i y j 139
Algoritmo de programação dinâmica: SSCOMÁX-COMPR (X, m, Y, n) 01 para i 1 até m faça 02 c[i,0] 0 03 para j 1 até n faça 04 c[0, j] 0 05 para i 1 até m faça 06 para j 1 até n faça 07 se x i = y j 08 então c[i, j] c[i 1, j 1] + 1 09 senão se c[i 1, j] c[i, j 1] 10 então c[i, j] c[i 1, j] 11 senão c[i, j] c[i, j 1] 12 devolva c[m, n] Consumo de tempo: O(mn) 140
AULA 22 Algoritmos gulosos (greedy) CLRS 16.2 141
Máximo e maximal S = coleção de subconjuntos de {1,..., n} Elemento X de S é máximo se não existe Y em S tal que Y > X. Elemento X de S é maximal se não existe Y em S tal que Y X. Exemplo: { {1,2}, {2,3}, {4,5}, {1,2,3}, {2,3,4,5}, {1,3,4,5} } {1,2} não é maximal {1,2,3} é maximal {2, 3, 4, 5} é maximal e máximo Problema 1: Encontrar elemento máximo de S. Usualmente difícil. Problema 2: Encontrar elemento maximal de S. Muito fácil: aplique algoritmo guloso. S tem estrutura gulosa se todo maximal é máximo. Se S tem estrutura gulosa, Problema 1 é fácil. 142
Algoritmos gulosos Algoritmo guloso procura maximal e acaba obtendo máximo procura ótimo local e acaba obtendo ótimo global costuma ser muito simples e intuitivo muito eficiente difícil provar que está correto Problema precisa ter subestrutura ótima (como na programação dinâmica) propriedade da escolha gulosa (greedy-choice property) 143
Algoritmo guloso, EXEMPLO 1: Caso especial da mochila booleana Dados inteiros não-negativos w 1,..., w n e W, encontrar um subconjunto máximo K de {1,..., n} dentre os que satisfazem k K w k W. Subestrutura ótima (já vimos): Se K é ótimo para (n, W) e n K então K {n} é ótimo para (n 1, W w n ) senão K é ótimo para (n 1, W). Propriedade da escolha gulosa: Se w n w i para todo i e w n W então n pertence a alguma solução ótima. Prove as propriedades! 144
Simplificação: basta dar tamanho de K ótimo Algoritmo guloso, versão recursiva, supondo w 1 w n : SS-REC (w, n, W) 1 se n = 0 ou w n > W 2 então devolva 0 3 senão devolva 1+SS-REC(w, n 1, W w n ) Consumo de tempo: T(n) = T(n 1) + O(1) Consumo de tempo: O(n) 145
Algoritmo guloso, versão iterativa, supondo w 1 w n : SS-ITER (w, n, W) 1 soma 0 2 para j n decrescendo até 1 faça 3 se w j > W 4 então devolva soma 5 senão soma soma + 1 6 W W w j 7 devolva soma Prove que o algoritmo está correto! Consumo de tempo: O(n) Prog din consumiria Θ(n 2 ) 146
AULA 23 Mais algoritmos gulosos CLRS 16.2 147
Algoritmo guloso, EXEMPLO 2: Problema dos intervalos disjuntos Dados intervalos [s 1, f 1 ),...,[s n, f n ), encontrar uma coleção máxima de intervalos disjuntos dois a dois. Solução é um subconjunto A de {1,..., n} Exemplo: s 1 f 1 Solução: Se cada intervalo é uma atividade, queremos coleção disjunta máxima de atividades compatíveis (i e j são compatíveis se f i s j ) 148
Análise do problema: Intervalos S := {1,..., n} Propriedade da escolha gulosa: Se f m é mínimo em S então m está em alguma solução ótima. Propriedade da subestrutura ótima: Suponha que f i é mínimo em S. Se A é solução ótima de S e A i então A {i} é solução ótima de S i. Notação: S i := {k : s k f i } (todos os intervalos à direita de i) Prove as propriedades! 149
Algoritmo guloso: Supõe f 1 f n Primeira versão: FEIO-INTERVALOS-DISJUNTOS (s, f, n) 1 A 2 i 1 3 enquanto i n faça 4 A A {i} 5 m i + 1 6 enquanto m n e s m < f i faça 7 m m + 1 8 i m 9 devolva A Correta, eficiente, mas deselegante. 150
Segunda versão: mais elegante Supõe f 1 f n INTERVALOS-DISJUNTOS (s, f, n) 1 A {1} 2 i 1 3 para m 2 até n faça 4 se s m f i 5 então A A {m} 6 i m 7 devolva A Consumo de tempo: Θ(n) Nome do algoritmo no CLRS: Greedy-Activity-Selector 151
AULA 24 Estrutura de dados para conjuntos disjuntos dinâmicos CLRS 21.1, 21.3 152
Exemplo de coleção disjunta dinâmica: componentes conexos de grafo dinâmico aresta componentes {a} {b} {c} {d} {e} (b, d) {a} {b, d} {c} {e} (c, e) {a} {b, d} {e, c} (c, d) {a} {b, d, c, e} (e, d) {a} {b, d, c, e} Operações básicas: MAKESET (x) UNION (x, y) FINDSET (x) x é elemento novo x e y em comps diferentes devolve representante do comp 153
Componentes conexos de um grafo G: CONNECTED-COMPONENTS (G) 1 para cada v em V [G] faça 2 MAKESET(v) 3 para cada (u, v) em E[G] faça 4 se FINDSET(u) FINDSET(v) 5 então UNION(u, v) Decide se u e v estão no mesmo componente: SAME-COMPONENT (u, v) 1 se FINDSET(u) = FINDSET(v) 2 então devolva SIM 3 senão devolva NÃO 154
Generalização: conjuntos disjuntos dinâmicos Seqüência de operações MAKESET, UNION, FINDSET M M M U F U U F U F F F U F } {{ } } n {{ } m Que estrutura de dados usar? Compromissos (trade-off s) Estrutura disjoint-set forest: cada conj tem uma raiz cada nó x tem um pai pai[x] = x se e só se x é uma raiz 155
MAKESET0 (x) 1 pai[x] x UNION0 (x, y) 1 x FINDSET0(x) 2 y FINDSET0(y) 3 pai[y ] x FINDSET0 (x) 1 enquanto pai[x] x 2 faça x pai[x] 3 devolva x Versão recursiva: FINDSET1 (x) 1 se pai[x] = x 2 então devolva x 3 senão devolva FINDSET1(pai[x]) 156
Custos: MAKESET0 O(1) UNION0 O(n) O(n) FINDSET0 M M M }{{} n U F U U F U F F F U F } {{ } m Custo total da seqüência: no(1) + no(n) + mo(n) = O(mn) 157
Melhoramento 1: rank[x] = pôsto do nó x MAKESET (x) 1 pai[x] x 2 rank[x] 0 UNION (x, y) com union by rank 1 x FINDSET(x) 2 y FINDSET(y) supõe que x y 3 se rank[x ] > rank[y ] 4 então pai[y ] x 5 senão pai[x ] y 6 se rank[x ] = rank[y ] 7 então rank[y ] rank[y ] + 1 altura(x) rank[x] lg n altura(x) := comprimento do mais longo caminho que vai de x até uma folha 158
Consumo de tempo: M M M }{{} n U F U U F U F F F U F } {{ } m altura(x) lg n Custos: MAKESET O(1) UNION O(lg n) FINDSET O(lg n) Custo total da seqüência: O(mlg n) 159
Melhoramento 2: FINDSET (x) com path compression 1 se x pai[x] 2 então pai[x] FINDSET(pai[x]) 3 devolva pai[x] Redação menos elegante: FINDSET (x) 1 se x = pai[x] 2 então devolva x 3 senão x FINDSET(pai[x]) 4 pai[x] x 5 devolva x Análise difícil: Custo amortizado de uma operação: O(lg n) 160
lg n é o menor k tal que lg lg... lg }{{} k n 1 n lg n 1 0 2 1 3 1 4 2 5 2.. 15 2 16 3.. 65535 3 65536 4.. 100000000000000000 000000000000 4 }{{} 80.. 161
AULA 25 Árvores geradora mínimas CLRS 23 162
Árvore geradora de grafo não-dirigido G = (V, E): A E tq (V, A) é conexo e não tem circuitos Cuidado: árvores não têm raiz, nem pais, nem filhos G tem árvore geradora G é conexo A é árvore geradora A = V 1 w(uv): peso da aresta uv w(a) = A w(uv): peso da árvore A Problema da árvore geradora mínima: Dados G e w, encontrar uma árvore geradora de peso mínimo Solução: avô de todos os algoritmos gulosos 163
Algoritmo genérico Recebe grafo conexo G com pesos w e devolve árvore geradora de peso mínimo GENERIC-MST (G, w) G conexo 1 A 2 enquanto A não é árvore geradora faça 3 (S, V S) corte que respeita A 4 uv aresta leve que cruza (S, V S) 5 A A {uv} 6 devolva A uv cruza (S, V S) se u S e v V S ou vice-versa (S, V S) respeita A se não é cruzado por aresta de A uv é leve se w(uv) é mínimo em (S, V S). Invariante: no começo de cada iteração, A faz parte de alguma árvore geradora mínima 164
Algoritmo de Kruskal MST-KRUSKAL (G, w) G conexo 1 A 2 para cada vértice v 3 faça MAKESET(v) 4 coloque arestas em ordem crescente de w 5 para cada uv em ordem crescente de w 6 faça se FINDSET(u) FINDSET(v) 7 então A A {uv} 8 UNION(u, v) 9 devolva A linha consumo 2 3 O(V ) 4 O(E lg E) 5 O(E) 6 O(E lg V ) 7 O(E) 8 O(E lg V ) total O(E lg E) total = O(E lg V ) pois E < V 2 165
Rascunho do algoritmo de Prim MST-PRIM (G, w) 01 A 02 escolha vértice r 03 S {r} G conexo 04 enquanto S V [G] faça 05 min 06 para cada aresta uv faça 07 se u / S 08 então u v 09 se u S e v / S e w(uv) < min 10 então min w(uv) 11 u u 12 v v 13 S S {v } 14 A A {u v } 15 devolva A Consumo de tempo: linha consumo 01 03 O(1) 04 05 O(V ) 06 12 O(V E) 13 14 O(V ) 15 O(1) total O(V E) 166
Algoritmo de Prim MST-PRIM (G, w) 00 escolha vértice r 01 para cada vértice u 02 faça chave[u] 03 π[u] NIL 04 chave[r] 0 05 A 06 Q V [G] G conexo 07 enquanto Q faça 08 u EXTRACT-MIN(Q, chave) 09 se u r então A A {π[u]u} 10 para cada v em Adj[u] faça 11 se v Q e w(uv) < chave[v] 12 então π[v] u 13 chave[v] w(uv) 14 devolve A listas de adjacência Adj[v] π[u] NIL π[u] V Q 167
Invariantes: no começo de cada iteração (V Q, A) é uma árvore para cada v Q tal que π[v] NIL chave[v] < e chave[v] = min{ w(vv ) : v V Q } 168
Consumo de tempo, supondo Q implementada como um min-heap: linha consumo 00 06 O(V ) 07 O(V ) 08 O(V lg V ) 09 O(V ) 10 12 O(E) v Adj[v] = 2 E 13 O(E lg V ) DECREASE-KEY 14 O(1) total O(V lg V + E lg V ) Total = O(E lg V ) pois E V 1 Note o método agregado de análise nas linhas 10 12 169
AULA 26 Análise amortizada CLR 18 ou CLRS 17 170
Análise amortizada Exemplo 1: Contador binário k 1 3 2 1 0 A INCREMENT (A, k) 1 i 0 2 enquanto i < k e A[i] = 1 3 faça A[i] 0 4 i i + 1 5 se i < k 6 então A[i] 1 Custo = consumo de tempo = = número de bits alterados = O(k) Seqüência de n chamadas: INCR INCR INCR INCR INCR }{{} n Custo = O(nk) Exagero! 171
A 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 0 n = 16 A[0] muda n vezes A[1] " n/2 " A[2] " n/4 " A[3] " n/8 " 172
Custo total: lg n i=0 n 2 i < n i=0 1 2 i = 2n = O(n) Custo amortizado (= custo fictício = = custo faz-de-conta) de uma operação: 2n n = O(1) Este foi o método agregado de análise: soma os custos de todas as operações para determinar o custo amortizado de cada operação 173
Outro método de análise: potencial A 0 1 a op A 1 2 a op A 2... n a op A n A i = estado de A depois da i a operação Custo real da i a operação: c i = t i + 1 onde t i = número de 1 0 na i a operação Energia potencial de A i : Φ(A i ) = número de bits 1 = Φ(A i 1 ) t i + 1 Custo amortizado da i a operação: ĉ i = c i + Φ(A i ) Φ(A i 1 ) = c i + Φ(A i 1 ) t i + 1 Φ(A i 1 ) = c i t i + 1 = (t i + 1) t i + 1 = 2 174
Soma dos custos amortizados limita a soma dos custos reais pois Φ 0: n i=1 ĉ i = (c i + Φ(A i ) Φ(A i 1 )) = c i + Φ(A n ) Φ(A 0 ) = c i + Φ(A n ) 0 = c i + Φ(A n ) c i Conclusão: ci ĉ i = 2n = O(n). Resumo da relação entre c, ĉ e Φ: ĉ i c i = Φ i Φ i 1 175
Exemplo 2: Tabelas dinâmicas 11111 22222 11111 22222 33333 33333 44444 55555 t 44444 n[t]= número de itens Inicialmente n[t] = t[t] = 0 TABLE-INSERT (T, x) 01 se t[t] = 0 02 então aloque tabela[t] com 1 posição 03 t[t] 1 04 se n[t] = t[t] 05 então aloque nova com 2 t[t] posições 06 insira itens da tabela[t] na nova 07 libere tabela[t] 08 tabela[t] nova 09 t[t] 2 t[t] 10 insira x na tabela[t] 11 n[t] n[t] + 1 Custo = número de inserções elementares (linhas 6 e 10) 176
Seqüência de n TABLE-INSERTs Custo real da i a operação: onde n i c i = 1 se há espaço 1 + n i 1 se tabela cheia = valor de n depois da i a operação = i Custo de uma operação = O(n) Custo das n operações = O(n 2 ). Exagero! Função potencial: Φ(T) := 2 n[t] t[t] Note que 0 Φ(T) t[t] 177
Cálculo do custo amortizado ĉ i : Se i a operação não causa expansão então ĉ i = c i + Φ i Φ i 1 = 1 + (2n i t i ) (2n i 1 t i 1 ) = 1 + (2n i t i ) (2(n i 1) t i ) = 3 n i, t i,φ i = valores depois da i a operação Se i a operação causa expansão então ĉ i = c i + Φ i Φ i 1 = n i + (2n i t i ) (2n i 1 t i 1 ) = n i + (2n i 2n i 1 ) (2n i 1 n i 1 ) = n i + 2n i 3n i 1 = n i + 2n i 3(n i 1) = 3 Conclusão: ĉ i = 3 para qualquer i 178
O custo real das n operações é limitado pelo custo amortizado pois Φ 0: n i=1 c i = ĉ i Φ n + Φ 0 = ĉ i Φ n ĉ i = 3n = O(n) 179
AULA 27 Complexidade computacional: P versus NP CLR 36 ou CLRS 34 180
Consumo de tempo de um algoritmo Complexidade de um problema Problemas e instâncias Instâncias = cadeias de caracteres N = tamanho de uma instância Exemplos problema da subseqüência crescente máxima problema subcoleção disjunta máxima de intervalos problema da mochila problema da árvore geradora de peso mínimo 181
Complexidade de um problema Problema polinomial: existe algoritmo O(N i ) para algum i Por que polinômios? Classe P de problemas Para muitos problemas, não se conhece algoritmo melhor que testar todas as possibilidades. (Exemplo: examinar todas as 2 n seqüs de n bits.) Em geral, isso não está em P. 182
Problemas de decisão: respostas SIM ou NÃO subseqüência crescente k subcoleção disjunta k de intervalos mochila de valor k árvore geradora de peso k Verificação de soluções Certificados de respostas SIM Certificados de respostas NÃO existe subseqüência crescente k? existe subcoleção disjunta k de intervalos? existe mochila de valor k? grafo tem árvore geradora de peso k? grafo tem circuito de comprimento k? grafo tem conjunto independente de tamanho k? grafo tem emparelhamento de tamanho k? 183
Certificados polinomiais Classe NP: resposta SIM tem certificado polinomial Não confunda NP com não-polinomial Classe conp: resposta NÃO tem certificado polinomial Fácil: P NP P conp Ninguém sabe: P? = NP 184
Redução entre problemas Converta instância de problema A em instância de B. Resolva instância de B. Converta solução de B em solução de A. Redução polinomial Permite comparar o grau de complexidade de problemas diferentes. 185
Problemas completos em NP A é completo em NP se todo problema em NP pode ser polinomialmente reduzido a A Classe NPC Classe dos problemas mais difíceis de NP P = NP P NPC Teorema de S. Cook: NPC mochila circuito hamiltoniano caminho máximo escalonamento de tarefas clique máximo 186