Você está na página 1de 203

AULA 01

PROJETO E ANÁLISE DE
ALGORITMOS
Introdução ao projeto e análise de
algoritmos
Karina Valdivia Delgado
Roteiro

Conceitos básicos: algoritmo, problema, instância


Prova de correção do algoritmo
Consumo de tempo
Projeto e análise de algoritmos

“Um projetista de algoritmos deve ser capaz de


prever o comportamento de um algoritmo antes de
implementá-lo.”
Algoritmo
É um procedimento computacional bem definido,
que recebe um conjunto de valores como entrada
e produz um conjunto de valores como saída.

É uma ferramenta para resolver problemas


computacionais.
Problema e instância
Um problema é definido por:
- Uma descrição dos parâmetros
- Uma descrição sobre as propriedades que a
resposta deve satisfazer.

Uma instância de um problema é obtida ao fixar


valores para todos os parâmetros do problema.
Problema e instância
Problema: Ordenar uma sequência a1, a2, …, an de
maneira crescente.
Entrada: a1, a2, …, an
Saída: a'1, a'2, …, a'n
Propriedades: a'1, a'2, …, a'n é uma permutação
de a1, a2, …, an tal que a'1 ≤ a'2≤ … ≤ a'n
Instância: 10 20 5 40 4
4 5 10 20 40
Problema e instância

Fonte: Flickr
Corretude do algoritmo

Um algoritmo é correto (resolve o problema) se,


para toda instância de entrada, o algoritmo termina
e produz uma saída que satisfaz as propriedades do
problema.

O primeiro passo é mostrar que o algoritmo de fato


resolve o problema, isto é, mostrar que ele faz o que
promete.
Corretude do algoritmo

Prova de correção do algoritmo:

-Para algoritmos iterativos é usada a técnica dos


invariantes do laço.

-Para algoritmos recursivos é usada indução


matemática no tamanho das instâncias.
Corretude do algoritmo
maximoRec (A,n)
1 se n = 1
2 então devolva A[1]
3 senão x = maximoRec (A, n-1) //x é o máximo de A[1..n-1]
4 se x > A[n]
5 então devolva x
6 senão devolva A[n]
Corretude do algoritmo
maximoRec (A,n)
1 se n = 1
2 então devolva A[1]
3 senão x = maximoRec (A, n-1) //x é o máximo de A[1..n-1]
4 se x > A[n]
5 então devolva x
6 senão devolva A[n]

Se n=1, o algoritmo devolve a resposta correta.


Corretude do algoritmo
maximoRec (A,n)
1 se n = 1
2 então devolva A[1]
3 senão x = maximoRec (A, n-1) //x é o máximo de A[1..n-1]
4 se x > A[n]
5 então devolva x
6 senão devolva A[n]

Podemos supor, por hipótese de indução, que para n ≥ 2


maximoRec(A,n-1) produz o resultado esperado.
Corretude do algoritmo
maximoRec (A,n)
1 se n = 1
2 então devolva A[1]
3 senão x = maximoRec (A, n-1) //x é o máximo de A[1..n-1]
4 se x > A[n]
5 então devolva x
6 senão devolva A[n]
Logo, no início da linha 4, x é o máximo dos elementos de A[1...n-1].
Considerando isso, as linhas 4 a 6 calculam corretamente o máximo
de A[1 . . n].
Consumo de tempo
Após provar se o algoritmo está correto podemos
analisar o consumo de tempo do algoritmo.

Para isso, vamos estimar quanto tempo a máquina


vai gastar ou quanto de memória será necessária
para resolver uma instância do problema.
Estimando o tempo de maneira experimental

Fonte: Própria
Ordenação
Problema: Ordenar um vetor A[1, …, n] de maneira
crescente.
Entrada:
23 20 21 28 27 22 25 24 29

Saída:

20 21 22 23 24 25 27 28 29
Ordenação por inserção 1

Até a posição j-1 o vetor está ordenado e vamos


tentar inserir o valor que está na posição j no lugar
certo.
j
20 21 23 27 28 22 25 24 29

chave=22
Algoritmo e simulação baseada em https://www.ime.usp.br/~coelho/algoritmos/aulas/material/intro.pdf
1
Ordenação por inserção
i j chave=22

20 21 23 27 28 22 25 24 29
i
20 21 23 27 28 25 24 29
i
20 21 23 27 28 25 24 29
i
20 21 23 27 28 25 24 29

20 21 22 23 27 28 25 24 29
Ordenação por inserção
i j chave=25

20 21 22 23 27 28 25 24 29
i
20 21 22 23 27 28 24 29
i
20 21 22 23 27 28 24 29

20 21 22 23 25 27 28 24 29
Ordenação por inserção
i j chave=24

20 21 22 23 25 27 28 24 29
i
20 21 22 23 25 27 28 29
i
20 21 22 23 25 27 28 29
i
20 21 22 23 25 27 28 29

20 21 22 23 24 25 27 28 29
Ordenação por inserção
chave=29 i j

20 21 22 23 24 25 27 28 29

20 21 22 23 24 25 27 28 29
Ordenação por inserção
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
Pior caso, melhor caso e caso médio
Para um vetor de tamanho n, quantas
comparações realiza o algoritmo?
Ordena por inserção
Número máximo de atribuições
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça n
2 chave ← A[j] n-1
3 i←j−1 n-1
4 enquanto i ≥ 1 e A[i] > chave faça 0
5 A[i + 1] ← A[i] ≤1+2+...+ n-1
6 i←i−1 ≤1+2+...+ n-1
7 A[i + 1] ← chave n-1
≤ n2+3n-3
Ordena por inserção
Cada linha consome 1 unidade de tempo
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça n
2 chave ← A[j] n-1
3 i←j−1 n-1
4 enquanto i ≥ 1 e A[i] > chave faça ≤2+3+...+ n
5 A[i + 1] ← A[i] ≤1+2+...+ n-1
6 i←i−1 ≤1+2+...+ n-1
7 A[i + 1] ← chave n-1
≤ (3n2+7n-8)/2
Ordena por inserção
Podemos considerar também que cada linha i de
código consome ti unidades de tempo, obtendo:
≤ c2n2+c1n+ c0

Temos: n2+3n-3, (3n2+7n-8)/2 e c2n2+c1n+ c0

Será que para n grande faz muita diferença?


Consumo de tempo
Vamos ficar satisfeitos com análises mais
aproximadas. Pretendemos medir a ordem de
grandeza da função de tempo do algoritmo.

Podemos formalizar estes conceitos com as


notações O, Ω e Θ
AULA 01
PROJETO E ANÁLISE DE
ALGORITMOS
Introdução ao projeto e análise de
algoritmos
Karina Valdivia Delgado
AULA 02
PROJETO E ANÁLISE DE
ALGORITMOS
Análise assintótica: ordens O, Ω e Θ
Parte I
Karina Valdivia Delgado
Roteiro
Introdução
Comparação assintótica de funções
Notação O
Exercícios
Introdução
Na aula anterior calculamos, de diferentes
formas, o consumo do algoritmo ordena por
inserção:
n2+3n-3
(3n2+7n-8)/2
c2n2+c1n+ c0
Vamos ficar satisfeitos com análises mais
aproximadas.
Note que n2 domina os outros termos.
Introdução

Seja T(n) o consumo de tempo (no pior caso,


no melhor caso ou no caso médio) do
algoritmo A, para instâncias de tamanho n.
Introdução
Precisamos ter um modo grosseiro de
comparar funções, que considere a velocidade
de crescimento das funções.

Pretendemos medir a ordem de grandeza da


função de tempo do algoritmo.
Introdução
No exemplo, ficamos satisfeitos em notar que,
no pior caso, o tempo cresce na proporção do
quadrado do tamanho da sequência.

Podemos formalizar estes conceitos com as


notações O, Ω e Θ, que permitem fazer uma
comparação assintótica de funções.
Comparação assintótica de funções
n6 n + 100000
(3n2+7n-8)/2

3n5+3n-3 83n3+3n-3 log n

2n+3n √n

Para n enorme, qual função cresce mais?


Comparação assintótica de funções
n6 n + 100000
(3n2+7n-8)/2

3n5+3n-3 83n3+3n-3 log n

2n+3n √n

Para n enorme, qual função cresce mais?


2n+3n, n6, 3n5+3n-3, 83n3+3n-3, (3n2+7n-8)/2,
n + 100000, √n, log n
Comparação assintótica de funções
Três tipos de comparação assintótica1:

- comparação com sabor de “≤” (O)


- comparação com sabor de “≥” (Ω)
- comparação com sabor de “=” (Θ)

1
FEOFILOFF, P. Minicurso de Análise de Algoritmos.
Notação O
O(f(n)) intuitivamente são funções que não
crescem mais rápido que f (n)

n2+3n-3 , (3n2+7n-8)/2 e c2n2+c1n+ c0 são O(n2)

n2+3n-3 é O(n2), isto é, n2+3n-3 não cresce mais rápido que


n2
(3n2+7n-8)/2 é O(n2), isto é, (3n2+7n-8)/2 não cresce mais
rápido que n2
c2n2+c1n+c0 é O(n2), isto é, c2n2+c1n+c0 não cresce mais
rápido que n2
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

lê-se:
T(n) é O de f(n)
ou
T(n) é da ordem
de f(n)
ou
T(n) ∈ O(f(n))
ou
abuso da
linguagem
T(n)=O(f(n))
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 1:
n²+800 é O(n²)

c=6
n0 = 14
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 2:
Demonstrar que n²+800 é O(n²)
Prova:
n²+800 ≤ n²+800*n² = 801 n² para todo n ≥ 1 => c=801 e
n0=1
Prova alternativa:
n²+800 ≤ n²+n*n = 2n² para todo n ≥ 800 => c=2 e n0=800
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 3:
Demonstrar que 100n² é O(n3)
Prova:
100n² ≤ n*n² = n3 para todo n ≥ 100 => c=1 e n0=100
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 4:
Demonstrar que 10n3-3n2+27 é O(n3)
Prova:
10n3-3n2+27 ≤ 10 n3 se (3n2-27)>=0 ou seja
10n3-3n2+27 ≤ 10 n3 para todo n ≥ 3 => c=10 e n0=3
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 5:
Demonstrar que n é O(2n)
Será provado por indução que n ≤ 2n para todo n ≥ 1 => c=1 e
n0=1:
Se n = 1 temos 1 ≤ 2 .
Para n ≥ 2 por hipótese de indução temos que (n − 1) ≤ 2 n−1.
Então n ≤ n + (n − 2) = (n − 1) + (n − 1) ≤ 2n−1 + 2n−1 = 2(2n−1)=2n .
Classes O

O(1) constante
O(lg n) logarítmica
O(n) linear
O(n lg n) n log n
O(n2 ) quadrática
O(n3 ) cúbica
O(nk ) com k >= 1 polinomial
O(2n ) exponencial
O(an ) com a > 1 exponencial
Ordena por inserção
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça O(n)
2 chave ← A[j] O(n)
3 i←j−1 O(n)
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

A linha 4 é executada um número de vezes menor que


n em cada iteração de j. Assim, ela consome nO(n)
Ordena por inserção
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça O(n)
2 chave ← A[j] O(n)
3 i←j−1 O(n)
4 enquanto i ≥ 1 e A[i] > chave faça nO(n) = O(n2)
5 A[i + 1] ← A[i] nO(n) = O(n2)
6 i←i−1 nO(n) = O(n2)
7 A[i + 1] ← chave O(n)
O(3n2+4n) = O(n2)
A linha 4 é executada um número de vezes menor que
n em cada iteração de j. Assim, ela consome nO(n)
Ordena por inserção
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça O(n)
2 chave ← A[j] O(n)
3 i←j−1 O(n)
4 enquanto i ≥ 1 e A[i] > chave faça nO(n) = O(n2)
5 A[i + 1] ← A[i] nO(n) = O(n2)
6 i←i−1 nO(n) = O(n2)
7 A[i + 1] ← chave O(n)
O(3n2+4n) = O(n2)
O algoritmo consome O(n2) unidades de tempo
Ordena por inserção
Quem demonstrou?

nO(n) = O(n2)
O(n)+O(n)+O(n)+O(n) = O(4n)
O(n2)+ O(n2)+O(n2) = O(3n2)
O(3n2)+O(4n)= O(3n2+4n)
O(3n2+4n) = O(n2)
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n)
para todo n ≥ n0.
Exemplo 6:
Demonstrar que O(n2)+ O(n2) = O(2n2)
Isso significa que se T(n) é O(n2) e G(n) é O(n2), então T(n)+G(n)
é O(2n2).
Prova: existem constantes positivas c1 e n01 tais que:
T(n) ≤ c1n2 para todo n ≥ n01 e existem constantes
positivas c2 e n02 tais que: G(n) ≤ c2n2 para todo n ≥ n02
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n)
para todo n ≥ n0.
Exemplo 6:
Demonstrar que O(n2)+ O(n2) = O(2n2)
Isso significa que se T(n) é O(n2) e G(n) é O(n2), então T(n)+G(n)
é O(2n2).
Prova: existem constantes positivas c1 e n01 tais que:
T(n) ≤ c1n2 para todo n ≥ n01 e existem constantes
positivas c2 e n02 tais que: G(n) ≤ c2n2 para todo n ≥ n02
T(n)+G(n) ≤ c1n2 +c2n2=2n2(c1 +c2)/2 => c=(c1 +c2)/2 e n0 =max{n01,n02}
AULA 02
PROJETO E ANÁLISE DE
ALGORITMOS
Análise assintótica: ordens O, Ω e Θ
Parte I
Karina Valdivia Delgado
AULA 02
PROJETO E ANÁLISE DE
ALGORITMOS
Análise assintótica: ordens O, Ω e Θ
Parte I
Karina Valdivia Delgado
Roteiro
Introdução
Comparação assintótica de funções
Notação O
Exercícios
Introdução
Na aula anterior calculamos, de diferentes
formas, o consumo do algoritmo ordena por
inserção:
n2+3n-3
(3n2+7n-8)/2
c2n2+c1n+ c0
Vamos ficar satisfeitos com análises mais
aproximadas.
Note que n2 domina os outros termos.
Introdução

Seja T(n) o consumo de tempo (no pior caso,


no melhor caso ou no caso médio) do
algoritmo A, para instâncias de tamanho n.
Introdução
Precisamos ter um modo grosseiro de
comparar funções, que considere a velocidade
de crescimento das funções.

Pretendemos medir a ordem de grandeza da


função de tempo do algoritmo.
Introdução
No exemplo, ficamos satisfeitos em notar que,
no pior caso, o tempo cresce na proporção do
quadrado do tamanho da sequência.

Podemos formalizar estes conceitos com as


notações O, Ω e Θ, que permitem fazer uma
comparação assintótica de funções.
Comparação assintótica de funções
n6 n + 100000
(3n2+7n-8)/2

3n5+3n-3 83n3+3n-3 log n

2n+3n √n

Para n enorme, qual função cresce mais?


Comparação assintótica de funções
n6 n + 100000
(3n2+7n-8)/2

3n5+3n-3 83n3+3n-3 log n

2n+3n √n

Para n enorme, qual função cresce mais?


2n+3n, n6, 3n5+3n-3, 83n3+3n-3, (3n2+7n-8)/2,
n + 100000, √n, log n
Comparação assintótica de funções
Três tipos de comparação assintótica1:

- comparação com sabor de “≤” (O)


- comparação com sabor de “≥” (Ω)
- comparação com sabor de “=” (Θ)

1
FEOFILOFF, P. Minicurso de Análise de Algoritmos.
Notação O
O(f(n)) intuitivamente são funções que não
crescem mais rápido que f (n)

n2+3n-3 , (3n2+7n-8)/2 e c2n2+c1n+ c0 são O(n2)

n2+3n-3 é O(n2), isto é, n2+3n-3 não cresce mais rápido que


n2
(3n2+7n-8)/2 é O(n2), isto é, (3n2+7n-8)/2 não cresce mais
rápido que n2
c2n2+c1n+c0 é O(n2), isto é, c2n2+c1n+c0 não cresce mais
rápido que n2
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

lê-se:
T(n) é O de f(n)
ou
T(n) é da ordem
de f(n)
ou
T(n) ∈ O(f(n))
ou
abuso da
linguagem
T(n)=O(f(n))
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 1:
n²+800 é O(n²)

c=6
n0 = 14
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 2:
Demonstrar que n²+800 é O(n²)
Prova:
n²+800 ≤ n²+800*n² = 801 n² para todo n ≥ 1 => c=801 e
n0=1
Prova alternativa:
n²+800 ≤ n²+n*n = 2n² para todo n ≥ 800 => c=2 e n0=800
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 3:
Demonstrar que 100n² é O(n3)
Prova:
100n² ≤ n*n² = n3 para todo n ≥ 100 => c=1 e n0=100
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 4:
Demonstrar que 10n3-3n2+27 é O(n3)
Prova:
10n3-3n2+27 ≤ 10 n3 se (3n2-27)>=0 ou seja
10n3-3n2+27 ≤ 10 n3 para todo n ≥ 3 => c=10 e n0=3
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n)
é O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 5:
Demonstrar que n é O(2n)
Será provado por indução que n ≤ 2n para todo n ≥ 1 => c=1 e
n0=1:
Se n = 1 temos 1 ≤ 2 .
Para n ≥ 2 por hipótese de indução temos que (n − 1) ≤ 2 n−1.
Então n ≤ n + (n − 2) = (n − 1) + (n − 1) ≤ 2n−1 + 2n−1 = 2(2n−1)=2n .
Classes O

O(1) constante
O(lg n) logarítmica
O(n) linear
O(n lg n) n log n
O(n2 ) quadrática
O(n3 ) cúbica
O(nk ) com k >= 1 polinomial
O(2n ) exponencial
O(an ) com a > 1 exponencial
Ordena por inserção
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça O(n)
2 chave ← A[j] O(n)
3 i←j−1 O(n)
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

A linha 4 é executada um número de vezes menor que


n em cada iteração de j. Assim, ela consome nO(n)
Ordena por inserção
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça O(n)
2 chave ← A[j] O(n)
3 i←j−1 O(n)
4 enquanto i ≥ 1 e A[i] > chave faça nO(n) = O(n2)
5 A[i + 1] ← A[i] nO(n) = O(n2)
6 i←i−1 nO(n) = O(n2)
7 A[i + 1] ← chave O(n)
O(3n2+4n) = O(n2)
A linha 4 é executada um número de vezes menor que
n em cada iteração de j. Assim, ela consome nO(n)
Ordena por inserção
ORDENA-POR-INSERÇÃO (A, n)
1 para j ← 2 até n faça O(n)
2 chave ← A[j] O(n)
3 i←j−1 O(n)
4 enquanto i ≥ 1 e A[i] > chave faça nO(n) = O(n2)
5 A[i + 1] ← A[i] nO(n) = O(n2)
6 i←i−1 nO(n) = O(n2)
7 A[i + 1] ← chave O(n)
O(3n2+4n) = O(n2)
O algoritmo consome O(n2) unidades de tempo
Ordena por inserção
Quem demonstrou?

nO(n) = O(n2)
O(n)+O(n)+O(n)+O(n) = O(4n)
O(n2)+ O(n2)+O(n2) = O(3n2)
O(3n2)+O(4n)= O(3n2+4n)
O(3n2+4n) = O(n2)
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n)
para todo n ≥ n0.
Exemplo 6:
Demonstrar que O(n2)+ O(n2) = O(2n2)
Isso significa que se T(n) é O(n2) e G(n) é O(n2), então T(n)+G(n)
é O(2n2).
Prova: existem constantes positivas c1 e n01 tais que:
T(n) ≤ c1n2 para todo n ≥ n01 e existem constantes
positivas c2 e n02 tais que: G(n) ≤ c2n2 para todo n ≥ n02
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n)
para todo n ≥ n0.
Exemplo 6:
Demonstrar que O(n2)+ O(n2) = O(2n2)
Isso significa que se T(n) é O(n2) e G(n) é O(n2), então T(n)+G(n)
é O(2n2).
Prova: existem constantes positivas c1 e n01 tais que:
T(n) ≤ c1n2 para todo n ≥ n01 e existem constantes
positivas c2 e n02 tais que: G(n) ≤ c2n2 para todo n ≥ n02
T(n)+G(n) ≤ c1n2 +c2n2=2n2(c1 +c2)/2 => c=(c1 +c2)/2 e n0 =max{n01,n02}
AULA 02
PROJETO E ANÁLISE DE
ALGORITMOS
Análise assintótica: ordens O, Ω e Θ
Parte I
Karina Valdivia Delgado
AULA 03
PROJETO E ANÁLISE DE
ALGORITMOS
Análise assintótica: ordens O, Ω e Θ
Parte II
Karina Valdivia Delgado
Roteiro

Notação Ω
Notação Θ
Revisão de matemática
Exercício adicional
Comparação assintótica de funções
Três tipos de comparação assintótica1:

- comparação com sabor de “≤” (O)


- comparação com sabor de “≥” (Ω)
- comparação com sabor de “=” (Θ)

1
FEOFILOFF, P. Minicurso de Análise de Algoritmos.
Notação O
Sejam T(n) e f(n) funções dos inteiros nos reais. Dizemos que T(n) é
O(f(n)) se existem constantes positivas c e n0 tais que:
T (n) ≤ c f(n) para todo n ≥ n0.
Notação Ω
Dizemos que T(n) é Ω(f(n)) se existem constantes positivas c e n0
tais que: T (n) ≥ c f(n) para todo n ≥ n0.
Notação Ω
Dizemos que T(n) é Ω(f(n)) se existem constantes positivas c e n0 tais
que: T (n) ≥ c f(n) para todo n ≥ n0.

Exemplo 1:
Demonstrar que 6n+5 é Ω(n)
Prova:
6n+5 ≥ 6n para todo n ≥ 0 => c=6 e n0=0
Notação Ω
Dizemos que T(n) é Ω(f(n)) se existem constantes positivas c e n0 tais
que: T (n) ≥ c f(n) para todo n ≥ n0.

Exemplo 2:
Demonstrar que n2-2 é Ω(n2)
Prova:
n2-2 ≥ n2/2+(n2/2-2) ≥ n2/2 se (n2/2-2) ≥ 0, isto é, para todo n ≥
2 => c=1/2 e n0=2.
Notação Ω
Dizemos que T(n) é Ω(f(n)) se existem constantes positivas c e n0 tais
que: T (n) ≥ c f(n) para todo n ≥ n0.

Exemplo 3:
Demonstrar que nlgn é Ω(n)
Prova:
lg n ≥ 1 para todo n ≥ 2 e portanto nlg n ≥ n => c=1 e n0=2.
Notação Θ
Dizemos que T(n) é Θ(f(n)) se existem constantes positivas c1
e c2 e n0 tais que: c1 f(n) ≤ T (n) ≤ c2 f(n) para todo n ≥ n0.
Notação Θ
Dizemos que T(n) é Θ(f(n)) se T(n) é O(f(n)) e T(n) é Ω(f(n)).
Notação Θ
Dizemos que T(n) é Θ(f(n)) se existem constantes positivas c1
e c2 e n0 tais que: c1 f(n) ≤ T (n) ≤ c2 f(n) para todo n ≥ n0.

Exemplo 4:
Demonstrar que n2-2 é Θ(n2)
Prova:
n2-2 ≥ n2/2+(n2/2-2) ≥ n2/2 se (n2/2-2) ≥ 0, isto é, para
todo n ≥ 2 => c1=½ e n01=2.

n2-2 ≤ n2 para todo n ≥ 0 => c2=1 e n02=0.

n2/2 ≤ n2-2 ≤ n2, c1=½, c2=1, n0=max{n01,n02 } = 2


Classes Θ

Θ(1) constante
Θ(lg n) logarítmica
Θ(n) linear
Θ(n lg n) n log n
Θ(n2 ) quadrática
Θ(n3 ) cúbica
Θ(nk ) com k >= 1 polinomial
Θ(2n ) exponencial
Θ(an ) com a > 1 exponencial
Classes Θ

Θ(1) constante

Θ(lg n) logarítmica

Θ(n) linear n multiplicado por 10, tempo multiplicado por 10


algoritmos considerados muito rápidos

Θ(n lg n) n log n com constantes razoáveis,


algoritmos considerados bem eficientes
Classes Θ

Θ(n2) quadrática n multiplicado por 10, tempo multiplicado por 100


algumas vezes podem ser satisfatórios

Θ(n3) cúbica n multiplicado por 10, tempo multiplicado por 1000


algumas vezes podem ser satisfatórios

Θ(nk) com k >= 1 polinomial. Exemplos: Θ(n), Θ(n2), Θ(n3), Θ(n50)


Classes Θ

Θ(2n ) exponencial n multiplicado por 10, tempo elevado a 10,


não úteis do ponto de vista prático

Θ(an ) com a > 1 exponencial Exemplos: Θ(2n), Θ(3n),


não úteis do ponto de vista prático
Propriedades

Transitividade:
T(n) é Θ(f(n)) e f(n) é Θ(g(n)) então T(n) é Θ(g(n))
T(n) é O(f(n)) e f(n) é O(g(n)) então T(n) é O(g(n))
T(n) é Ω(f(n)) e f(n) é Ω(g(n)) então T(n) é Ω(g(n))

Reflexividade
T(n) é Θ(T(n))
T(n) é O(T(n))
T(n) é Ω(T(n))
Propriedades

Simétrica:
T(n) é Θ(f(n)) então f(n) é Θ(T(n))

Antissimétrica
T(n) é O(f(n)) então f(n) é Ω(T(n))
T(n) é Ω(f(n)) então f(n) é O(T(n))
Revisão de matemática
Expoentes:
xn * xm = xn + m
xn / xm = xn - m
(xn) m= xn *m
xn+xn= 2xn

Logaritmos:
loga(b*c) = logab + logac
loga(b/c) = logab – logac
logabm = m * logab
logab = logcb/ logca
Revisão de matemática
Somatórias:
Exercício adicional
Dizemos que T(n) é O(f(n)) se existem constantes positivas c e
n0 tais que: T (n) ≤ c f(n) para todo n ≥ n0.

Exemplo 5: (Regra da soma geral)


Suponha T1(n)=O(f1(n)) e T2(n) = O(f2(n)). Se f1(n) = O(f2(n)),
mostre que T1(n) + T2(n) = O(f2(n)).
Exercício adicional
Exemplo 5: (Regra da soma geral)
Suponha T1(n)=O(f1(n)) e T2(n) = O(f2(n)). Se f1(n) = O(f2(n)),
mostre que T1(n) + T2(n) = O(f2(n)).
Prova:
Existem constantes positivas c1 e n01 tais que: T1(n) ≤ c1f1(n)
para todo n ≥ n01
Existem constantes positivas c2 e n02 tais que: T2(n) ≤ c2f2(n)
para todo n ≥ n02.
Existem constantes positivas c3 e n03 tais que: f1(n) ≤ c3f2(n)
para todo n ≥ n03.
Exercício adicional
Exemplo 5: (Regra da soma geral)
Suponha T1(n)=O(f1(n)) e T2(n) = O(f2(n)). Se f1(n) = O(f2(n)),
mostre que T1(n) + T2(n) = O(f2(n)).
Prova:
Existem constantes positivas c1 e n01 tais que: T1(n) ≤ c1f1(n)
para todo n ≥ n01
Existem constantes positivas c2 e n02 tais que: T2(n) ≤ c2f2(n)
para todo n ≥ n02.
Existem constantes positivas c3 e n03 tais que: f1(n) ≤ c3f2(n)
para todo n ≥ n03.
Assim,
T1(n) + T2(n) ≤ c1f1(n) +c2f2(n) ≤ c1c3f2(n)+ c2f2(n) =f2(n)(c1c3 +c2) =>
AULA 03
PROJETO E ANÁLISE DE
ALGORITMOS
Análise assintótica: ordens O, Ω e Θ
Parte II
Karina Valdivia Delgado
AULA 04
PROJETO E ANÁLISE DE
ALGORITMOS
Divisão e conquista
Equações de recorrência
Karina Valdivia Delgado
Roteiro

Divisão e conquista
Algoritmo MergeSort
Equações de recorrência
Divisão e conquista
Muitos algoritmos conhecidos têm uma estrutura
recursiva.

O problema é dividido recursivamente e suas


soluções combinadas para obter uma solução do
problema original.
Divisão e conquista
Passos em cada nível de recursão:

- Divisão: o problema é dividido em subproblemas menores.


Deve ser rápido.
- Conquista:
- os subproblemas são resolvidos recursivamente e
- subproblemas pequenos são resolvidos diretamente.
- Combinação: as soluções dos subproblemas são
combinadas. Deve ser rápido.
MergeSort
Problema: Ordenar um vetor A[p, …, r] de maneira
crescente.
Entrada:
p r
23 20 21 28 27 22 25 24 29
MergeSort
Problema: Ordenar um vetor A[p, …, r] de maneira
crescente.
Entrada:
p r
23 20 21 28 27 22 25 24 29
Dividir
p q q+1 r
23 20 21 28 27 22 25 24 29
MergeSort
Problema: Ordenar um vetor A[p, …, r] de maneira
crescente.
Entrada:
p r
23 20 21 28 27 22 25 24 29
Conquistar
p q q+1 r
20 21 23 27 28 22 24 25 29
MergeSort
Problema: Ordenar um vetor A[p, …, r] de maneira
Problema:
crescente.
Rearranjar A[p...r] de forma crescente
Entrada:
considerando
p A[p ...q] e A[q+1...r] crescentes
r
Algoritmo
23 20 INTERCALA
21 28 27 22 25 24 29
Conquistar
p q q+1 r
20 21 23 27 28 22 24 25 29
MergeSort
Problema: Ordenar um vetor A[p, …, r] de maneira
Problema:
crescente.
Rearranjar A[p...r] de forma crescente
Entrada:
considerando
p A[p ...q] e A[q+1...r] crescentes
r
Algoritmo
23 20 INTERCALA
21 28 27 22 25 24 29
Combinar
p q q+1 r
20 21 22 23 24 25 27 28 29
MergeSort
Problema:
Rearranjar
Problema: A[p...r]
Ordenar de A[p,
um vetor forma
…, r]crescente
de maneira
considerando A[p ...q] e A[q+1...r] crescentes
crescente.
Algoritmo INTERCALA
Entrada:
Considerando
p n=r-p+1, podemos criar um r
algoritmo
23 20 que
21 faça
28 isso
27 em22Θ(n)25 24 29
Combinar
p q q+1 r
20 21 22 23 24 25 27 28 29
MergeSort

MERGE-SORT (A, p, r)1


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)
1
Pseudocódigo e simulação baseados em https://www.ime.usp.br/~coelho/algoritmos/aulas/material/aula4.pdf
MergeSort

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)
O algoritmo está correto?
MergeSort

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)
A correção se apoia na correção do algoritmo INTERCALA e pode
ser demonstrada por indução em n=r-p+1
MergeSort

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)
Se p=r, isto é, n=1, o algoritmo devolve a resposta correta.
MergeSort
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)
Podemos supor, por hipótese de indução, que para n ≥ 2 MERGE-
SORT(A,p,q) e MERGE-SORT(A,q+1,r) produz o resultado
esperado pois os trechos que estão sendo ordenados têm
tamanho menor que n.
MergeSort
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)

Considerando que o INTERCALA está correto, garantimos que o


trecho de tamanho n está ordenado.
MergeSort

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)
Agora queremos saber qual o consumo de tempo?
MergeSort

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)
Seja T(n) o tempo máximo gasto pelo algoritmo
para ordenar um trecho de tamanho n=r-p+1
MergeSort

MERGE-SORT (A, p, r)
1 se p < r Θ(1)
2 então q ← ⌊(p + r)/2⌋ Θ(1)
3 MERGE-SORT (A, p, q) T(⌈n/2⌉)
4 MERGE-SORT (A, q + 1, r) T(⌊n/2⌋)
5 INTERCALA (A, p, q, r) Θ(n)
MergeSort

MERGE-SORT (A, p, r)
1 se p < r Θ(1)
2 então q ← ⌊(p + r)/2⌋ Θ(1)
3 MERGE-SORT (A, p, q) T(⌈n/2⌉)
4 MERGE-SORT (A, q + 1, r) T(⌊n/2⌋)
5 INTERCALA (A, p, q, r) Θ(n)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(n+2) para n=2,3,...
T(1) = Θ(1)
MergeSort

MERGE-SORT (A, p, r)
1 se p < r Θ(1)
2 T(n)=?q ← ⌊(p + r)/2⌋
então Θ(1)
3 T(n) éMERGE-SORT
Θ(?), é Θ(nlogn)?, é Θ(n²)?,
(A, p, q) é ⌉)
T(⌈n/2
4 Θ(n²logn)?
MERGE-SORT (A, q + 1, r) T(⌊n/2⌋)
5 INTERCALA (A, p, q, r) Θ(n)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(n+2) para n=2,3,...
T(1) = Θ(1)
Recorrências
Para calcular o consumo de tempo utilizamos
equações de recorrência.

Uma equação de recorrência é uma maneira de


definir uma função por uma expressão em termos
dela mesma.
Recorrências
Para calcular o consumo de tempo utilizamos
equações de recorrência.

Uma equação de recorrência é uma maneira de


definir uma função por uma expressão em termos
Queremos
dela mesma. resolver a recorrência, isto é,
obter uma fórmula fechada para T(n)
que dê o valor da função diretamente
em termos de seu argumento.
Máximo recursivo
Calcular o máximo de um vetor A[p…r]
Algoritmo Máximo (A, p, r)
1. se p = r
2. então devolva A[p]
3. senão q ← ⌊ (p+r)/2 ⌋
4. m1 ←Máximo (A, p, q)
5. m2 ←Máximo (A, q + 1, r)
6. se m1 > m2
7. então devolva m1
8. senão devolva m2
Máximo recursivo
Algoritmo Máximo (A, p, r)
1. se p = r
2. então devolva A[p]
3. senão q ← ⌊ (p+r)/2 ⌋
4. m1 ←Máximo (A, p, q)
5. m2 ←Máximo (A, q + 1, r)
6. se m1 > m2
7. então devolva m1
8. senão devolva m2
Seja T(n) o tempo máximo gasto pelo algoritmo para
encontrar o valor máximo de um trecho de tamanho n=r-p+1
Máximo recursivo
Algoritmo Máximo (A, p, r)
1. se p = r Θ(1)
2. então devolva A[p] Θ(1)
3. senão q ← ⌊ (p+r)/2 ⌋ Θ(1)
4. m1 ←Máximo (A, p, q) T(⌈n/2⌉)
5. m2 ←Máximo (A, q + 1, r) T(⌊n/2⌋)
6. se m1 > m2 Θ(1)
7. então devolva m1 Θ(1)
8. senão devolva m2 Θ(1)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(6) para n=2,3,...
T(1) = Θ(1)
Máximo recursivo
Algoritmo Máximo (A, p, r)
1. se p = r Θ(1)
2. então devolva A[p] Θ(1)
3. senão q ← ⌊ (p+r)/2 ⌋ Θ(1)
4. T(n)=?m1 ←Máximo (A, p, q) T(⌈n/2⌉)
5. T(n) ém2 Θ(?), é Θ(n)?,
←Máximo (A, q +é1,Θ(nlogn)?
r) T(⌊n/2⌋é)
6. Θ(n²)?se
é Θ(n²logn)?
m1 > m2 Θ(1)
7. então devolva m1 Θ(1)
8. senão devolva m2 Θ(1)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(6) para n=2,3,...
T(1) = Θ(1)
AULA 04
PROJETO E ANÁLISE DE
ALGORITMOS
Divisão e conquista
Equações de recorrência
Karina Valdivia Delgado
AULA 05
PROJETO E ANÁLISE DE
ALGORITMOS
Solução de recorrências (Parte I)
Karina Valdivia Delgado
Roteiro

Divisão e Conquista e equação de recorrência.

Teorema mestre
Divisão e Conquista
Passos em cada nível de recursão:

- Divisão: O problema é dividido em subproblemas menores.


Deve ser rápido.
- Conquista:
- Os subproblemas são resolvidos recursivamente.
- Subproblemas pequenos são resolvidos diretamente.
- Combinação: as soluções dos subproblemas são
combinadas. Deve ser rápido.
MergeSort

MERGE-SORT (A, p, r)
1 se p < r Θ(1)
2 então q ← ⌊(p + r)/2⌋ Θ(1)
3 MERGE-SORT (A, p, q) T(⌈n/2⌉)
4 MERGE-SORT (A, q + 1, r) T(⌊n/2⌋)
5 INTERCALA (A, p, q, r) Θ(n)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(n+2) para n=2,3,...
T(1) = Θ(1)
MergeSort

MERGE-SORT (A, p, r)
1 se p < r Θ(1)
2 T(n)=?q ← ⌊(p + r)/2⌋
então Θ(1)
3 T(n) éMERGE-SORT
Θ(?), é Θ(nlogn)?, é Θ(n²)?,
(A, p, q) é ⌉)
T(⌈n/2
4 Θ(n²logn)?
MERGE-SORT (A, q + 1, r) T(⌊n/2⌋)
5 INTERCALA (A, p, q, r) Θ(n)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(n+2) para n=2,3,...
T(1) = Θ(1)
Consumo de tempo de
algoritmos Divisão e Conquista
Para uma entrada de tamanho n, o consumo de
tempo é:
T(n) = Dividir(n) + Conquistar(n) + Combinar(n).
Suponha que o problema é dividido em a
subproblemas, cada um com 1/b do tamanho
original. Qual o consumo do passo de Conquista?
Consumo de tempo de
algoritmos Divisão e Conquista
Para uma entrada de tamanho n, o consumo de
tempo é:
T(n) = Dividir(n) + Conquistar(n) + Combinar(n).
Suponha que o problema é dividido em a
subproblemas, cada um com 1/b do tamanho
original. Qual o consumo do passo de Conquista?
aT(n/b)
Consumo de tempo de
algoritmos Divisão e Conquista
O consumo de tempo é:
T(n) = Dividir(n) + aT(n/b) + Combinar(n).
Em geral temos:
T(n) = aT(n/b) + f (n)
a representa o número de subproblemas obtidos na
Divisão, n/b representa o tamanho de cada
subproblema e f(n) é a função que representa o
consumo das etapas de Divisão e Combinação
Resolver recorrências

Queremos resolver a recorrência, isto é, obter


uma fórmula fechada para T(n) que dê o valor
da função diretamente em termos de seu
argumento.
Resolver recorrências
Alguns métodos para resolução de
recorrências:
- Substituição
- Iteração
- Árvore de recorrência
- Teorema mestre (quase sem fazer contas,
porém, não funciona para todos os casos).
Resolver recorrências
Alguns métodos para resolução de
recorrências:
- Substituição
- Iteração
- Árvore de recorrência
- Teorema mestre (quase sem fazer contas,
porém, não funciona para todos os casos).
Teorema Mestre
Suponha
T (n) = a T (n/b) + f (n)
para algum a ≥ 1 e b > 1 e em que n/b significa ⌈n/b ⌉ ou
⌊n/b⌋. Então, em geral:

(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log ba )


(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ba lg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))
para qualquer ε > 0 .
Teorema Mestre
No caso (3) temos que verificar a condição de regularidade:
af(n/b) ≤ cf(n)
para alguma constante c<1 e n suficiente grande.

Observação 1: quando f(n) é um polinômio, a condição de


regularidade se cumpre.

Observação 2: mesmo para funções no formato


T(n)=aT(n/b)+f (n), o Teorema Mestre pode não ser aplicável.
Exemplo 1
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 1: Resolva
T(n) =1 se n=1
T(n) = 4 T(⌊n/2⌋) + n se n>1
Exemplo 1
(1) se f (n) = O(n log Ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 1: Resolva
T(n) =1 se n=1
T(n) = 4 T(⌊n/2⌋) + n se n>1
a=4 b=2 f(n) = n
nlog ba=nlog 42= n2 f(n) está “por cima” ou “por baixo” de nlog a ? b
Exemplo 1
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log a blg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 1: Resolva
T(n) =1 se n=1
T(n) = 4 T(⌊n/2⌋) + n se n>1
a=4 b=2 f(n) = n
b 2
n log ba
=n log 4
= n2 f(n) está “por cima” ou “por baixo” de nlog a ?
f(n)=n=O(n2−ε) para ε =?
Exemplo 1
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 1: Resolva
T(n) =1 se n=1
T(n) = 4 T(⌊n/2⌋) + n se n>1
a=4 b=2 f(n) = n
log ba log 42
n b =n = n2 f(n) está “por cima” ou “por baixo” de nlog a ?
f(n)=n=O(n2−ε) para ε =1 (caso 1)
T(n) = Θ(n2)
Exemplo 2
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))
Exemplo 2: Resolva
T(n) = T(⌊2n/3⌋) + 1
Exemplo 2
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log a blg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 2: Resolva
T(n) = T(⌊2n/3⌋) + 1

a=1 b=3/2 f(n) = 1


b 3/2
n log ba
=n log 1
=n0=1, f(n) está “por cima” ou “por baixo” de nlog a ?
Exemplo 2
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log a blg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 2: Resolva
T(n) = T(⌊2n/3⌋) + 1

a=1 b=3/2 f(n) = 1


log ba log 3/2
n b =n 1=n0=1, f(n) está “por cima” ou “por baixo” de nlog a ?
f(n)=1=Θ(1) (caso 2)
T(n) = Θ(1*lgn)=Θ(lgn)
Exemplo 3
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log ab )
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))
Exemplo 3: Resolva
T(n) = 3T(n/4) + nlgn, para n=4,8,12,16, ….
Exemplo 3
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log ab )
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 3: Resolva
T(n) = 3T(n/4) + nlgn, para n=4,8,12,16, ….

a=3 b=4 f(n) = nlgn


b 4
n log ba
=n log 3
=n0,8, f(n) está “por cima” ou “por baixo” de n log a ?
Exemplo 3
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log ab )
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 3: Resolva
T(n) = 3T(n/4) + nlgn, para n=4,8,12,16, ….

a=3 b=4 f(n) = nlgn


nlog bba=nlog 43=n0,8, f(n) está “por cima” ou “por baixo” de n log a ?
f(n)=nlgn=Ω(n0,8+ε), para ε ≈ ?
Exemplo 3
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log ab )
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 3: Resolva
T(n) = 3T(n/4) + nlgn, para n=4,8,12,16, ….

a=3 b=4 f(n) = nlgn


log ba log 43
n b =n =n0,8, f(n) está “por cima” ou “por baixo” de n log a ?
f(n)=nlgn=Ω(n0,8+ε), para ε ≈ 0.2 (caso 3)
Temos ainda que verificar a condição de regularidade...
Exemplo 3
No caso (3) temos que verificar a condição de regularidade:
af(n/b) ≤ cf(n)
para alguma constante c<1 e n suficiente grande.
Exemplo 3: Resolva
T(n) = 3T(n/4) + nlgn, para n=4,8,12,16, ….

a=3 b=4 f(n) = nlgn

3*f(n/4)=3*[n/4 lg (n/4)] = ¾ n (lgn - lg4) = ¾ nlgn - 3/2 n


≤ ¾ nlgn para todo n ≥ 1, c=¾ <1.
Exemplo 3
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))

Exemplo 3: Resolva
T(n) = 3T(n/4) + nlgn, para n=4,8,12,16, ….

a=3 b=4 f(n) = nlgn


nlog ba=nlog 43=n0,8, f(n) está “por cima” ou “por baixo” de nlog a ?b
f(n)=nlgn=Ω(n0,8+ε), para ε ≈ 0.2 (caso 3)
Temos ainda que verificar a condição de regularidade...OK
T(n)=Θ(nlogn)
Dicas práticas
A solução da recorrência:
T(1) = Θ(1)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ Θ(n+2), para n=2,3,...
Representa todas as recorrências da forma:
T(1) = Θ(1)
T(n) = T(⌈n/2⌉)+ T(⌊n/2⌋)+ f(n), em que f(n) é Θ(n+2)=Θ(n)
Está na mesma classe Θ que a solução de
T′(1) = 1
T′(n) = 2T′(n/2) + n para n = 2, 22 , 23, . . .
Está na mesma classe Θ que a solução de
T''(2) = 20
T''(n) = 2T''(n/2) + n para n = 22 , 23, . . .
Exemplo 4
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log a blg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))
Exemplo 4: Resolva
T(n) = 2T(n/2)+ n

a=2 b=2 f(n) = n


nlog ba=nlog 22=n, f(n) está “por cima” ou “por baixo” de n log a ?b
f(n)=n=Θ(n1) (caso 2)

T(n)=Θ(nlogn)
Exemplo 4
(1) se f (n) = O(n log ba−ε ) então T (n) = Θ(n log a b)
(2) se f (n) = Θ(n log ba ) então T (n) = Θ(n log ablg n)
(3) se f (n) = Ω(n log ba+ε ) então T (n) = Θ(f (n))
Exemplo 4: Resolva
T(n) = 2T(n/2)+ n

a=2 b=2 f(n) = n


nlog Ba=nlog 22=n, f(n) está “por cima” ou “por baixo” de n log a ?b
f(n)=n=Θ(n1) (caso 2)

O consumo de tempo de MergeSort é T(n)=Θ(nlogn)


Exemplos em que o Teorema
Mestre não funciona
T(n) = T(n − 1) + n log(n)
T(n) = 2T(n/2) + n log(n) por quê?
T(n) = T(n − 1) + log(n)
T (n) = T (n − 2) + O(n)
T (n) = 5T (n − 1) + O(n)
AULA 05
PROJETO E ANÁLISE DE
ALGORITMOS
Solução de recorrências (Parte I)
Karina Valdivia Delgado
AULA 06
PROJETO E ANÁLISE DE
ALGORITMOS
Solução de recorrências (Parte II)
Karina Valdivia Delgado
Roteiro

Método Iteração
Árvore de recorrência
Método de substituição
Resolver recorrências

Queremos resolver a recorrência, isto é, obter


uma fórmula fechada para T(n) que dê o valor
da função diretamente em termos de seu
argumento.
Exemplo
Resolver:
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...
Exemplo
Resolver:
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

n 1 2 4 8 16 32 64 ...
T(n) 1
Exemplo
Resolver:
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

n 1 2 4 8 16 32 ...
T(n) 1 4
Exemplo
Resolver:
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

n 1 2 4 8 16 32 ...
T(n) 1 4 10 22 46 94
Exemplo
Resolver:
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

n 1 2 4 8 16 32 ...
T(n) 1 4 10 22 46 94
3n-2 1 4 10 22 46 94
Exemplo
Resolver:
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, …

n 1 2 4 8 16 32 ...
T(n) 1 4 10 22 46 94
3n-2 1 4 10 22 46 94

Eu acho que T(n)=3n-2, será que isso é verdade?


Método da iteração
Método da iteração
Consiste em expandir, isto é, iterar a
recorrência e escrevê-la como uma somatória
de termos que dependem apenas de n.
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2) + 2 it 1
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2)+2 it 1

= 2*[ 2*T(n/4) +2]+2 = 2² T(n/4)+6 it 2


Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2)+2 it 1
= 2*[ 2*T(n/4)+2]+2 = 2² T(n/2²)+6 it 2
= 2*[ 2*[2*T(n/8)+2]+2]+2 = 2³T(n/2³)+14 it 3
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2)+2²-2 it 1
= 2*[ 2*T(n/4)+2]+2 = 2² T(n/2²)+2³-2 it 2
= 2*[ 2*[2*T(n/8)+2]+2]+2 = 2³T(n/2³)+2⁴-2 it 3
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2)+2²-2 it 1
= 2*[ 2*T(n/4)+2]+2 = 2² T(n/2²)+2³-2 it 2
= 2*[ 2*[2*T(n/8)+2]+2]+2 = 2³T(n/2³)+2⁴-2 it 3
e para a i-ésima iteração?
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2)+2²-2 it 1
= 2*[ 2*T(n/4)+2]+2 = 2² T(n/2²)+2³-2 it 2
= 2*[ 2*[2*T(n/8)+2]+2]+2 = 2³T(n/2³)+2⁴-2 it 3
e para a i-ésima iteração?
= 2iT(n/2i)+2i+1-2 it i
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 2*T(n/2)+2²-2 it 1
= 2*[ 2*T(n/4)+2]+2 = 2² T(n/2²)+2³-2 it 2
= 2*[ 2*[2*T(n/8)+2]+2]+2 = 2³T(n/2³)+2⁴-2 it 3
e para a i-ésima iteração?
= 2iT(n/2i)+2i+1-2 it i
Quando vou chegar no caso base (quando vou parar)?
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

e para a i-ésima iteração?


= 2iT(n/2i)+2i+1-2 it i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

e para a i-ésima iteração?


= 2iT(n/2i)+2i+1-2 it i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn, substituindo na fórmula da it i, temos:
T(n) = nT(1)+2n-2 =3n-2
Exemplo
T(1) = 1
T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

e para a i-ésima iteração?


T(n)=3n-2 → T(n)= Θ (n)
= 2 i
T(n/2 i
)+2 i+1
Será que o resultado que-2 encontrei está correto? it i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn, substituindo na fórmula da it i temos:
T(n) = 2lgnT(n/2lgn)+21+lgn-2 = n T(1)+2n-2 =3n-2
Árvore de recorrência
Árvore de recorrência
- É útil para estimar a solução de uma
recorrência.
- Representa em uma árvore o desenvolvimento
da recorrência. Permite visualizar melhor o que
acontece quando a recorrência é iterada.
- Cada nó da árvore representa um subproblema.
- Para calcular o consumo de tempo total, são
somados todos os custos por nível.
T(1) = 1
Exemplo T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no
folhas

T(n)
0 1
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no
folhas

2
0 1 2

T(n/2) T(n/2) 1 2
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no
folhas

2
0 1 2

2 2 1 2 22

T(n/4) T(n/4) T(n/4) T(n/4) 2 22


Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no
folhas

2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/23) T(n/23) T(n/23) T(n/23) T(n/23) T(n/23) T(n/23) T(n/23)
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3 3 3 3 3 3

...
i-1 2i-1 2i
T(n/2i) … T(n/2i) i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3 3 3 3 3 3

...
i-1 2i-1 2i
T(1) … T(1) i 2i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3 3 3 3 3 3

...
i-1 2i-1 2i
T(1) … T(1) i 2i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1) i

n/2i=1 → n= 2i → i=lgn T(n)=2+22+23+...+2i+2i= 2i+ ∑ 2k


k=1
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3n 3 3 3 3 3

∑ aj = ...
(an+1-1)/ (a-1)
j=0

i-1 2i-1 2i
T(1) … T(1) i 2i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1) i

n/2i=1 → n= 2i → i=lgn T(n)=2+22+23+...+2i+2i= 2i+ ∑ 2k


k=1
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3n 3 3 3 3 3

∑ aj = ...
(an+1-1)/ (a-1)
j=0

i-1 2i-1 2i
T(1) … T(1) i 2i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1) i i

n/2i=1 → n= 2i → i=lgn T(n)=2+22+23+...+2i+2i= 2i+ ∑ 2k =2i+ ∑ 2k- 2⁰ = 2i+ (2i+1-1)/(2-1) - 1


k=1 k=0
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3n 3 3 3 3 3

∑ aj = ...
(an+1-1)/ (a-1)
j=0

i-1 2i-1 2i
T(1) … T(1) i 2i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn T(n)= 2i+ (2i+1-1)/(2-1) - 1 = n+ 2n-1-1= 3n-2
Exemplo T(1) = 1
T(n) = 2*T(n/2) + 2
nível no ∑
folhas
2
0 1 2
2 2 1 2 22

2 2 2 2 2 22 23

3 23
T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 ) T(n/2 )
3 3 3 3 3 3 3 3
T(n)=3n-2 ...
→ T(n)= Θ (n)
Será que o resultado que encontrei está correto?
i-1 2i-1 2i
T(1) … T(1) i 2i 2i
Quando vou chegar no caso base (quando vou parar)?
Quando T(n/2i)=T(1)
n/2i=1 → n= 2i → i=lgn T(n)= 2i+ (2i+1-1)/(2-1) - 1 = n+ 2n-1-1= 3n-2
Método da substituição
Método da iteração
O método começa com um “chute” para o
valor de T(n).

Após isso, é demonstrado por indução que o


“chute” está certo.
T(1) = 1
Exemplo T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 3n-2 para n = 1, 2, 4, 8, 16, 32 . . .


Prova:
Se n = 1 então T(1) = 3(1)-2 = 1
T(1) = 1
Exemplo T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 3n-2 para n = 1, 2, 4, 8, 16, 32 . . .


Prova:
Se n = 1 então T(1) = 3(1)-2 = 1
Se n ≥ 2 então
T(n) = 2*T(n/2) + 2
T(1) = 1
Exemplo T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 3n-2 para n = 1, 2, 4, 8, 16, 32 . . .


Prova:
Se n = 1 então T(1) = 3(1)-2 = 1
Se n ≥ 2 então
T(n) = 2*T(n/2) + 2
hi
= 2*[ 3(n/2)-2 ] + 2
T(1) = 1
Exemplo T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 3n-2 para n = 1, 2, 4, 8, 16, 32 . . .


Prova:
Se n = 1 então T(1) = 3(1)-2 = 1
Se n ≥ 2 então
T(n) = 2*T(n/2) + 2
hi
= 2*[ 3(n/2)-2 ] + 2
= 3n - 4 +2
= 3n-2
T(1) = 1
Exemplo T(n) = 2*T(n/2) + 2, para n=2, 4, 8, ..., 2i, ...

T(n) = 3n-2 para n = 1, 2, 4, 8, 16, 32 . . .


Prova:
Se n = 1 então T(1) = 3(1)-2 = 1
Se n ≥ 2 então
T(n) = 2*T(n/2) + 2
T(n)=3n-2
hi → T(n)= Θ (n)
= 2*[ 3(n/2)-2 ] + 2
= 3n - 4 +2
= 3n-2
AULA 06
PROJETO E ANÁLISE DE
ALGORITMOS
Solução de recorrências (Parte II)
Karina Valdivia Delgado

Você também pode gostar