Lista de exercícios

Exercícios resolvidos: complexidade de algoritmos

Lista progressiva e comentada sobre contagem de instruções, crescimento assintótico e análise de recorrências.

Esta lista pratica os conceitos da Aula 01 em uma sequência progressiva. Tente resolver cada exercício antes de consultar a solução. O tempo indicado nos metadados é apenas uma estimativa de estudo, não um limite.

Cada exercício é seguido pela respectiva solução. A resolução registra as premissas, os cálculos intermediários e a conclusão.

Exercício 1: contagem exata com execução condicional

Analise o fragmento abaixo:

long sum_even(const int values[], size_t count) {
    long total = 0L;

    for (size_t index = 0U; index < count; index++) {
        if (values[index] % 2 == 0) {
            total += values[index];
        }
    }

    return total;
}

Considere uma unidade para cada:

  • inicialização de total;
  • inicialização de index;
  • teste index < count;
  • incremento index++;
  • teste que verifica se o valor é par;
  • atualização de total;
  • retorno da função.

Seja n=countn = \text{count} e seja ee a quantidade de valores pares.

  1. Escreva T(n,e)T(n,e).
  2. Calcule o melhor caso.
  3. Calcule o pior caso.
  4. Calcule T(7,3)T(7,3).
  5. Classifique o melhor e o pior caso com Θ\Theta.
Solução

Explicação

Identificação das variáveis

O tamanho da entrada é nn, pois o arranjo possui count elementos.

A variável ee informa quantas vezes o corpo do if executa. Logo:

0en0 \le e \le n

Trace do laço

Considere count = 4. Cada linha abaixo representa uma avaliação de index < count:

Avaliaçãoindex antes do testeTesteResultadoO que acontece depois
100 < 4verdadeiroO corpo executa e index++ produz 1.
211 < 4verdadeiroO corpo executa e index++ produz 2.
322 < 4verdadeiroO corpo executa e index++ produz 3.
433 < 4verdadeiroO corpo executa e index++ produz 4.
544 < 4falsoO laço termina. O corpo e o incremento não executam.

Os quatro elementos produzem quatro testes verdadeiros. O laço precisa de mais um teste, agora falso, para descobrir que deve terminar. Portanto, para nn elementos, index < count é avaliado n+1n+1 vezes. O corpo e index++ executam somente nn vezes.

Contagem de cada operação

total = 0L                         1 vez
index = 0U                         1 vez
index < count                      n + 1 vezes
index++                            n vezes
values[index] % 2 == 0             n vezes
total += values[index]             e vezes
return total                       1 vez

Construção de T(n,e)T(n,e)

Somando as quantidades:

T(n,e)=1+1+(n+1)+n+n+e+1T(n,e) = 1 + 1 + (n+1) + n + n + e + 1

Agrupando os termos:

T(n,e)=3n+e+4T(n,e) = 3n + e + 4

Melhor e pior caso

O melhor caso ocorre quando nenhum valor é par. Nesse caso, e=0e=0:

T(n,0)=3n+0+4=3n+4T(n,0) = 3n + 0 + 4 = 3n + 4

O termo dominante é nn. Portanto:

T(n,0)=Θ(n)T(n,0) = \Theta(n)

O pior caso ocorre quando todos os valores são pares. Nesse caso, e=ne=n:

T(n,n)=3n+n+4=4n+4T(n,n) = 3n + n + 4 = 4n + 4

O termo dominante continua sendo nn. Portanto:

T(n,n)=Θ(n)T(n,n) = \Theta(n)

Cálculo para n=7n=7 e e=3e=3

T(7,3)=37+3+4T(7,3) = 3 \cdot 7 + 3 + 4 T(7,3)=21+3+4=28T(7,3) = 21 + 3 + 4 = 28

Resposta esperada

  1. T(n,e)=3n+e+4T(n,e)=3n+e+4.
  2. No melhor caso, e=0e=0 e T(n,0)=3n+4T(n,0)=3n+4.
  3. No pior caso, e=ne=n e T(n,n)=4n+4T(n,n)=4n+4.
  4. T(7,3)=28T(7,3)=28.
  5. O melhor e o pior caso pertencem a Θ(n)\Theta(n).

Exercício 2: quantidade de pares processados

Analise o fragmento abaixo. Considere que cada chamada de process possui custo constante e não usa espaço auxiliar que cresça com nn.

void process_pairs(const int values[], size_t count) {
    for (size_t left = 0U; left < count; left++) {
        for (size_t right = 0U; right < left; right++) {
            process(values[left], values[right]);
        }
    }
}

Conte somente as chamadas de process.

  1. Quantas chamadas ocorrem para cada valor de left?
  2. Escreva a soma C(n)C(n) que representa todas as chamadas.
  3. Obtenha uma fórmula fechada.
  4. Calcule C(9)C(9).
  5. Classifique o tempo e o espaço auxiliar.
Solução

Explicação

O que deve ser contado

O enunciado pede somente as chamadas de process. Uma chamada ocorre para cada par (left, right) em que o laço alcança o corpo, isto é, quando right < left é verdadeiro.

Trace em forma de matriz

Considere n=5n=5. As linhas representam left e as colunas representam right. O símbolo X marca uma chamada de process. O símbolo · indica que process não é chamado naquela combinação. Ele não significa que a condição foi necessariamente avaliada.

left / right01234Chamadas
0·····0
1X····1
2XX···2
3XXX··3
4XXXX·4

Os X formam o triângulo estritamente inferior da matriz, abaixo da diagonal em que right = left. Na linha left, existem exatamente left símbolos X e, portanto, left chamadas de process.

Soma das chamadas

C(n)=0+1+2++(n1)C(n) = 0 + 1 + 2 + \cdots + (n-1)

O termo zero não altera a soma. Essa é a soma dos inteiros de 11 até n1n-1, cuja fórmula é:

C(n)=n(n1)2C(n) = \frac{n(n-1)}{2}

Expandindo a expressão:

C(n)=n2n2C(n) = \frac{n^2-n}{2}

Chamadas de process e avaliações da condição não são a mesma contagem

Para cada valor de left, o teste right < left ocorre left vezes com resultado verdadeiro e mais uma vez com resultado falso. Esse último teste falso encerra o laço interno. Assim, a quantidade total de avaliações da condição é:

1+2+3++n=n(n+1)21 + 2 + 3 + \cdots + n = \frac{n(n+1)}{2}

Esse valor não responde ao enunciado, pois a avaliação falsa não chama process. A contagem solicitada inclui somente os X da matriz, isto é, n(n1)2\frac{n(n-1)}{2} chamadas.

Cálculo para n=9n=9

C(9)=9(91)2C(9) = \frac{9(9-1)}{2} C(9)=982=36C(9) = \frac{9 \cdot 8}{2} = 36

Classificação do tempo e do espaço

O termo dominante de (n2n)/2(n^2-n)/2 é n2n^2. A constante 1/21/2 e o termo n-n não alteram a classe assintótica:

C(n)=Θ(n2)C(n) = \Theta(n^2)

O fragmento usa apenas os índices left e right, além dos parâmetros. A quantidade de variáveis não cresce com nn:

S(n)=Θ(1)S(n) = \Theta(1)

Resposta esperada

  1. Para cada valor de left, ocorrem left chamadas de process.
  2. C(n)=0+1+2++(n1)C(n)=0+1+2+\cdots+(n-1).
  3. C(n)=n(n1)2C(n)=\frac{n(n-1)}{2}.
  4. C(9)=36C(9)=36.
  5. O tempo pertence a Θ(n2)\Theta(n^2) e o espaço auxiliar pertence a Θ(1)\Theta(1).

Exercício 3: valores concretos e taxas de crescimento

Considere três custos:

TA(n)=7n+30T_A(n)=7n+30 TB(n)=2nlog2n+10T_B(n)=2n\log_2 n+10 TC(n)=n22T_C(n)=\frac{n^2}{2}
  1. Calcule os três custos para n=16n=16.
  2. Ordene os algoritmos do menor para o maior custo nesse valor de nn.
  3. Determine a classe Θ\Theta de cada função.
  4. Ordene as classes pela taxa de crescimento.
  5. Para F(n)=6n2+3n+12F(n)=6n^2+3n+12, escreva limites OO, Ω\Omega e Θ\Theta usando a ordem dominante.
Solução

1. Cálculo de TA(16)T_A(16)

TA(16)=716+30T_A(16)=7\cdot16+30 TA(16)=112+30=142T_A(16)=112+30=142

2. Cálculo de TB(16)T_B(16)

Como 24=162^4=16, temos log216=4\log_2 16=4:

TB(16)=2164+10T_B(16)=2\cdot16\cdot4+10 TB(16)=128+10=138T_B(16)=128+10=138

3. Cálculo de TC(16)T_C(16)

TC(16)=1622T_C(16)=\frac{16^2}{2} TC(16)=2562=128T_C(16)=\frac{256}{2}=128

Para n=16n=16, a ordem concreta é:

TC(16)<TB(16)<TA(16)T_C(16) < T_B(16) < T_A(16)

4. Classes assintóticas

Em TA(n)=7n+30T_A(n)=7n+30, o termo dominante é nn:

TA(n)=Θ(n)T_A(n)=\Theta(n)

Em TB(n)=2nlog2n+10T_B(n)=2n\log_2 n+10, o termo dominante é nlognn\log n:

TB(n)=Θ(nlogn)T_B(n)=\Theta(n\log n)

Em TC(n)=n2/2T_C(n)=n^2/2, o termo dominante é n2n^2:

TC(n)=Θ(n2)T_C(n)=\Theta(n^2)

As taxas de crescimento ficam nesta ordem:

Θ(n)<Θ(nlogn)<Θ(n2)\Theta(n) < \Theta(n\log n) < \Theta(n^2)

O custo quadrático foi o menor para n=16n=16 por causa dos coeficientes das funções. Isso não altera o fato de que n2n^2 cresce mais rapidamente quando nn aumenta.

5. Limites de F(n)F(n)

Em F(n)=6n2+3n+12F(n)=6n^2+3n+12, o termo dominante é n2n^2. Usando a mesma ordem dominante nos três limites:

F(n)=O(n2)F(n)=O(n^2) F(n)=Ω(n2)F(n)=\Omega(n^2) F(n)=Θ(n2)F(n)=\Theta(n^2)

Resposta: para n=16n=16, os custos são 142142, 138138 e 128128. Assintoticamente, as classes são Θ(n)\Theta(n), Θ(nlogn)\Theta(n\log n) e Θ(n2)\Theta(n^2).

Exercício 4: modelagem de recorrências

Escreva o caso base e a recorrência de cada procedimento. Use T(1)=Θ(1)T(1)=\Theta(1) como caso base.

Procedimento A

  • cria duas chamadas com entradas de tamanho n/2n/2;
  • após as chamadas, percorre todos os nn elementos três vezes.

Procedimento B

  • cria uma chamada com entrada de tamanho n/4n/4;
  • após a chamada, executa duas operações constantes.

Procedimento C

  • cria quatro chamadas com entradas de tamanho n/2n/2;
  • após as chamadas, executa n2n^2 operações locais.

Para cada procedimento:

  1. identifique o custo das chamadas recursivas;
  2. identifique o trabalho local;
  3. escreva a recorrência completa.
Solução

Procedimento A

Duas chamadas com tamanho n/2n/2 produzem:

2T(n2)2T\left(\frac{n}{2}\right)

Três percursos completos executam 3n3n operações. Como o fator 33 é constante:

3n=Θ(n)3n=\Theta(n)

A recorrência pode preservar o coeficiente exato:

T(1)=Θ(1)T(1)=\Theta(1) T(n)=2T(n2)+3nT(n)=2T\left(\frac{n}{2}\right)+3n

Na forma assintótica do trabalho local:

T(n)=2T(n2)+Θ(n)T(n)=2T\left(\frac{n}{2}\right)+\Theta(n)

Procedimento B

Uma chamada com tamanho n/4n/4 produz:

T(n4)T\left(\frac{n}{4}\right)

Duas operações formam um custo constante:

2=Θ(1)2=\Theta(1)

Logo:

T(1)=Θ(1)T(1)=\Theta(1) T(n)=T(n4)+2T(n)=T\left(\frac{n}{4}\right)+2

ou:

T(n)=T(n4)+Θ(1)T(n)=T\left(\frac{n}{4}\right)+\Theta(1)

Procedimento C

Quatro chamadas com tamanho n/2n/2 produzem:

4T(n2)4T\left(\frac{n}{2}\right)

O enunciado informa trabalho local quadrático. Portanto:

T(1)=Θ(1)T(1)=\Theta(1) T(n)=4T(n2)+n2T(n)=4T\left(\frac{n}{2}\right)+n^2

ou:

T(n)=4T(n2)+Θ(n2)T(n)=4T\left(\frac{n}{2}\right)+\Theta(n^2)

Resposta: os termos recursivos representam a quantidade e o tamanho das chamadas. O termo após a soma representa somente o trabalho local da chamada atual.

Exercício 5: resolução pelo método iterativo

Considere nn como uma potência de 33:

T(1)=4T(1)=4 T(n)=T(n3)+2T(n)=T\left(\frac{n}{3}\right)+2
  1. Faça três expansões.
  2. Escreva a expressão após kk expansões.
  3. Determine kk por meio do caso base.
  4. Obtenha a fórmula exata de T(n)T(n).
  5. Classifique a função com Θ\Theta.
  6. Calcule T(729)T(729).
Solução

1. Três primeiras expansões

A primeira aplicação da recorrência é:

T(n)=T(n3)+2T(n)=T\left(\frac{n}{3}\right)+2

Na segunda aplicação, use a mesma regra com entrada n/3n/3:

T(n3)=T(n9)+2T\left(\frac{n}{3}\right)=T\left(\frac{n}{9}\right)+2

Substituindo na expressão original:

T(n)=[T(n9)+2]+2T(n)=\left[T\left(\frac{n}{9}\right)+2\right]+2 T(n)=T(n9)+4T(n)=T\left(\frac{n}{9}\right)+4

Na terceira aplicação:

T(n9)=T(n27)+2T\left(\frac{n}{9}\right)=T\left(\frac{n}{27}\right)+2

Logo:

T(n)=T(n27)+6T(n)=T\left(\frac{n}{27}\right)+6

Cada aplicação divide o tamanho por 33 e acrescenta 22.

2. Padrão após kk expansões

T(n)=T(n3k)+2kT(n)=T\left(\frac{n}{3^k}\right)+2k

3. Quantidade de expansões

A expansão termina quando a entrada chega a 11:

n3k=1\frac{n}{3^k}=1

Multiplicando os dois lados por 3k3^k:

n=3kn=3^k

Aplicando logaritmo de base 33:

k=log3nk=\log_3 n

4. Fórmula final

Substituindo k=log3nk=\log_3 n no padrão:

T(n)=T(1)+2log3nT(n)=T(1)+2\log_3 n

Como T(1)=4T(1)=4:

T(n)=4+2log3nT(n)=4+2\log_3 n

O termo dominante é logarítmico:

T(n)=Θ(logn)T(n)=\Theta(\log n)

5. Cálculo para n=729n=729

Como 729=36729=3^6:

log3729=6\log_3 729=6 T(729)=4+26=16T(729)=4+2\cdot6=16

Resposta: T(n)=4+2log3n=Θ(logn)T(n)=4+2\log_3 n=\Theta(\log n) e T(729)=16T(729)=16.

Exercício 6: verificação pelo método de substituição

Considere:

T(1)=2T(1)=2 T(n)=T(n1)+3T(n)=T(n-1)+3

Use substituição e indução para verificar a proposta:

T(n)=3n1T(n)=3n-1

A resolução deve conter:

  1. verificação do caso base;
  2. hipótese para n1n-1;
  3. substituição da hipótese na recorrência;
  4. conclusão exata e assintótica.
Solução

1. Caso base

A recorrência informa:

T(1)=2T(1)=2

A proposta para n=1n=1 fornece:

311=23\cdot1-1=2

O valor proposto coincide com o caso base.

2. Hipótese de indução

Suponha que a proposta seja válida para n1n-1:

T(n1)=3(n1)1T(n-1)=3(n-1)-1

Simplificando:

T(n1)=3n31T(n-1)=3n-3-1 T(n1)=3n4T(n-1)=3n-4

3. Substituição na recorrência

A recorrência é:

T(n)=T(n1)+3T(n)=T(n-1)+3

Substituindo a hipótese T(n1)=3n4T(n-1)=3n-4:

T(n)=(3n4)+3T(n)=(3n-4)+3 T(n)=3n1T(n)=3n-1

O resultado coincide com a proposta.

4. Conclusão

O caso base é válido e a hipótese para n1n-1 produz a expressão para nn. Portanto:

T(n)=3n1T(n)=3n-1

O termo dominante é nn:

T(n)=Θ(n)T(n)=\Theta(n)

Resposta: a proposta T(n)=3n1T(n)=3n-1 foi verificada e pertence a Θ(n)\Theta(n).

Exercício 7: árvore de recursão com níveis equilibrados

Considere nn como uma potência de 22:

T(1)=2T(1)=2 T(n)=2T(n2)+2nT(n)=2T\left(\frac{n}{2}\right)+2n
  1. Construa os níveis para n=16n=16.
  2. Informe a quantidade de nós, o tamanho da entrada e o custo local total de cada nível.
  3. Calcule a quantidade e o custo total das folhas.
  4. Calcule T(16)T(16).
  5. Generalize o custo do nível ii.
  6. Obtenha a classe assintótica.
Solução

1. Interpretação da recorrência

Em uma chamada com entrada de tamanho xx:

  • o termo 2T(x/2)2T(x/2) cria duas chamadas com metade da entrada;
  • o termo 2x2x representa o trabalho local da chamada atual;
  • uma folha custa T(1)=2T(1)=2.

2. Níveis para n=16n=16

Nível 0:  1 nó  de tamanho 16    custo por nó: 32    custo do nível: 32
Nível 1:  2 nós de tamanho 8     custo por nó: 16    custo do nível: 32
Nível 2:  4 nós de tamanho 4     custo por nó: 8     custo do nível: 32
Nível 3:  8 nós de tamanho 2     custo por nó: 4     custo do nível: 32
Nível 4: 16 folhas de tamanho 1  custo por folha: 2  custo do nível: 32

Existem quatro níveis internos, numerados de 00 a 33. O nível 44 contém os casos base.

3. Custo exato para n=16n=16

Os quatro níveis internos custam 3232 cada:

432=1284\cdot32=128

As 1616 folhas custam 22 cada:

162=3216\cdot2=32

Somando:

T(16)=128+32=160T(16)=128+32=160

4. Generalização do nível ii

No nível interno ii:

quantidade de noˊs=2i\text{quantidade de nós}=2^i tamanho por noˊ=n2i\text{tamanho por nó}=\frac{n}{2^i}

O custo local de um nó com entrada n/2in/2^i é:

2n2i2\cdot\frac{n}{2^i}

Multiplicando a quantidade de nós pelo custo de cada nó:

2i2n2i=2n2^i\cdot2\cdot\frac{n}{2^i}=2n

Todos os níveis internos custam 2n2n.

5. Altura e custo total

A árvore alcança o caso base quando:

n2k=1\frac{n}{2^k}=1

Logo:

k=log2nk=\log_2 n

Existem log2n\log_2 n níveis internos. O custo interno é:

2nlog2n2n\log_2 n

Existem nn folhas, cada uma com custo 22. O custo das folhas é 2n2n:

T(n)=2nlog2n+2nT(n)=2n\log_2 n+2n

Portanto:

T(n)=Θ(nlogn)T(n)=\Theta(n\log n)

Resposta: T(16)=160T(16)=160. Cada nível interno custa 2n2n, e o custo total pertence a Θ(nlogn)\Theta(n\log n).

Exercício 8: árvore de recursão dominada pelas folhas

Considere nn como uma potência de 22:

T(1)=1T(1)=1 T(n)=4T(n2)+2nT(n)=4T\left(\frac{n}{2}\right)+2n
  1. Construa os níveis para n=8n=8.
  2. Calcule o custo local total de cada nível interno.
  3. Calcule a quantidade de folhas.
  4. Calcule T(8)T(8).
  5. Generalize o custo do nível ii.
  6. Explique por que o resultado não recebe um fator adicional logn\log n.
Solução

1. Interpretação da recorrência

Cada chamada com entrada xx:

  • cria quatro chamadas com entrada x/2x/2;
  • executa 2x2x unidades de trabalho local;
  • termina com custo 11 quando x=1x=1.

2. Níveis para n=8n=8

Nível 0:  1 nó  de tamanho 8     custo por nó: 16    custo do nível: 16
Nível 1:  4 nós de tamanho 4     custo por nó: 8     custo do nível: 32
Nível 2: 16 nós de tamanho 2     custo por nó: 4     custo do nível: 64
Nível 3: 64 folhas de tamanho 1  custo por folha: 1  custo do nível: 64

3. Custo exato para n=8n=8

T(8)=16+32+64+64T(8)=16+32+64+64 T(8)=176T(8)=176

4. Generalização do custo interno

No nível interno ii:

quantidade de noˊs=4i\text{quantidade de nós}=4^i tamanho por noˊ=n2i\text{tamanho por nó}=\frac{n}{2^i} custo local por noˊ=2n2i\text{custo local por nó}=2\cdot\frac{n}{2^i}

O custo total do nível é:

4i2n2i4^i\cdot2\cdot\frac{n}{2^i}

Como 4i/2i=2i4^i/2^i=2^i:

custo do nıˊvel=2n2i\text{custo do nível}=2n\cdot2^i

O custo dobra a cada descida na árvore.

5. Quantidade de folhas

A altura kk satisfaz:

n2k=1\frac{n}{2^k}=1 k=log2nk=\log_2 n

Como a quantidade de nós é multiplicada por 44 em cada nível:

folhas=4k\text{folhas}=4^k

Substituindo k=log2nk=\log_2 n:

4k=(22)k=(2k)2=n24^k=(2^2)^k=(2^k)^2=n^2

As folhas custam 11 cada. Logo, o último nível custa n2n^2.

6. Custo assintótico

Os custos aumentam geometricamente em direção às folhas. Vistos de baixo para cima, os níveis anteriores formam frações sucessivas do custo dominante:

n2+n22+n24+n^2+\frac{n^2}{2}+\frac{n^2}{4}+\cdots

A soma dos níveis anteriores é menor que outro n2n^2:

n2T(n)<2n2n^2 \le T(n) < 2n^2

Portanto:

T(n)=Θ(n2)T(n)=\Theta(n^2)

O fator logn\log n não aparece porque os níveis não possuem o mesmo custo. O último nível domina a soma.

Resposta: T(8)=176T(8)=176, existem n2n^2 folhas e T(n)=Θ(n2)T(n)=\Theta(n^2).

Exercício 9: método mestre com domínio das folhas

Considere:

T(n)=8T(n2)+n2T(n)=8T\left(\frac{n}{2}\right)+n^2
  1. Identifique aa, bb e f(n)f(n).
  2. Calcule p=logbap=\log_b a.
  3. Compare f(n)f(n) com npn^p.
  4. Identifique o caso do método mestre.
  5. Obtenha a classe assintótica.

Use o mapa abaixo para organizar a comparação entre f(n)f(n) e nlogban^{\log_b a} antes de abrir a solução.

flowchart TD
    A["Identificar a, b e f(n)"] --> B["Calcular n elevado a log_b(a)"]
    B --> C{"Comparar f(n)"}
    C -->|Menor por fator polinomial| D["Caso 1"]
    C -->|Mesma ordem assintótica| E["Caso 2"]
    C -->|Maior por fator polinomial| F["Verificar regularidade"]
    F -->|Condição satisfeita| G["Caso 3"]
Solução

1. Parâmetros

A forma do método mestre é:

T(n)=aT(nb)+f(n)T(n)=aT\left(\frac{n}{b}\right)+f(n)

Comparando com a recorrência do exercício:

a = 8      porque existem oito subproblemas
b = 2      porque cada subproblema recebe n/2
f(n) = n²  porque esse é o trabalho local

2. Expoente de referência

p=logbap=\log_b a p=log28=3p=\log_2 8=3

Portanto:

np=n3n^p=n^3

3. Comparação dos expoentes

O trabalho local é:

f(n)=n2f(n)=n^2

O expoente local é c=2c=2, enquanto o expoente de referência é p=3p=3:

c<pc<p 2<32<3

O trabalho local possui uma potência menor. Portanto, as folhas dominam e o caso 1 se aplica.

4. Resultado

No caso 1:

T(n)=Θ(np)T(n)=\Theta(n^p)

Substituindo p=3p=3:

T(n)=Θ(n3)T(n)=\Theta(n^3)

Resposta: a=8a=8, b=2b=2, f(n)=n2f(n)=n^2, p=3p=3, o caso 1 se aplica e T(n)=Θ(n3)T(n)=\Theta(n^3).

Exercício 10: método mestre com níveis equilibrados e domínio da raiz

Resolva as duas recorrências com o método mestre.

Recorrência A

T(n)=9T(n3)+n2T(n)=9T\left(\frac{n}{3}\right)+n^2

Recorrência B

T(n)=2T(n2)+n3T(n)=2T\left(\frac{n}{2}\right)+n^3

Para cada recorrência:

  1. identifique aa, bb, f(n)f(n) e p=logbap=\log_b a;
  2. compare o expoente de f(n)f(n) com pp;
  3. identifique o caso;
  4. verifique a regularidade quando necessária;
  5. obtenha a classe assintótica.
Solução

Recorrência A: identificação dos parâmetros

a = 9
b = 3
f(n) = n²

O expoente de referência é:

p=log39=2p=\log_3 9=2

Logo:

np=n2n^p=n^2

O trabalho local também é f(n)=n2f(n)=n^2. Portanto, o expoente local c=2c=2 é igual a p=2p=2:

c=pc=p

Os níveis são equilibrados e o caso 2 se aplica:

T(n)=Θ(nplogn)T(n)=\Theta(n^p\log n)

Substituindo p=2p=2:

T(n)=Θ(n2logn)T(n)=\Theta(n^2\log n)

Recorrência B: identificação dos parâmetros

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

O expoente de referência é:

p=log22=1p=\log_2 2=1

Logo:

np=nn^p=n

O trabalho local possui expoente c=3c=3:

c>pc>p 3>13>1

Antes de usar o caso 3, é necessário verificar a regularidade:

af(nb)qf(n),q<1a\cdot f\left(\frac{n}{b}\right)\le q\cdot f(n), \quad q<1

Substituindo a=2a=2, b=2b=2 e f(n)=n3f(n)=n^3:

2f(n2)=2(n2)32\cdot f\left(\frac{n}{2}\right)=2\left(\frac{n}{2}\right)^3 2(n38)=n342\left(\frac{n^3}{8}\right)=\frac{n^3}{4}

Como f(n)=n3f(n)=n^3:

n34=14f(n)\frac{n^3}{4}=\frac{1}{4}f(n)

Podemos usar q=1/4q=1/4, que é menor que 11. A regularidade é satisfeita.

No caso 3, o trabalho local domina:

T(n)=Θ(f(n))T(n)=\Theta(f(n)) T(n)=Θ(n3)T(n)=\Theta(n^3)

Resposta: a recorrência A usa o caso 2 e resulta em Θ(n2logn)\Theta(n^2\log n). A recorrência B usa o caso 3, satisfaz a regularidade com q=1/4q=1/4 e resulta em Θ(n3)\Theta(n^3).

Exercício 11: decisão sobre a aplicação do método mestre

Para cada recorrência, informe se os três casos do método mestre apresentados na aula podem ser usados. Quando o método puder ser usado, determine a classe assintótica. Quando não puder, indique a condição que falha.

A. T(n)=T(n2)+n\text{A. } T(n)=T(n-2)+n B. T(n)=T(n4)+T(3n4)+n\text{B. } T(n)=T\left(\frac{n}{4}\right)+T\left(\frac{3n}{4}\right)+n C. T(n)=4T(n2)+n2logn\text{C. } T(n)=4T\left(\frac{n}{2}\right)+\frac{n^2}{\log n} D. T(n)=2T(n2)+n2\text{D. } T(n)=2T\left(\frac{n}{2}\right)+n^2
Solução

Recorrência A

O método exige subproblemas com tamanho n/bn/b, em que b>1b>1 é constante.

Na recorrência A, a entrada diminui por subtração:

n2n-2

Não existe uma divisão por um fator constante bb. Portanto, a recorrência não possui a forma exigida.

Decisão: rejeitar o método mestre apresentado na aula.

Recorrência B

O método exige que todos os subproblemas tenham o mesmo tamanho n/bn/b.

Nesta recorrência, os tamanhos são diferentes:

n4\frac{n}{4}

e:

3n4\frac{3n}{4}

Não é possível representar as duas chamadas por um único termo aT(n/b)aT(n/b).

Decisão: rejeitar o método mestre apresentado na aula.

Recorrência C

Os parâmetros iniciais são:

a = 4
b = 2
p = log₂ 4 = 2
nᵖ = n²
f(n) = n² / log n

O trabalho local é menor que n2n^2, mas a diferença ocorre somente pelo fator logarítmico 1/logn1/\log n. O caso 1 apresentado na aula exige uma diferença por potência:

f(n)=O(npε)f(n)=O(n^{p-\varepsilon})

para alguma constante ε>0\varepsilon>0.

O fator 1/logn1/\log n não fornece essa diferença de potência. O caso 2 também não serve porque f(n)f(n) não pertence a Θ(n2)\Theta(n^2).

Decisão: rejeitar os três casos apresentados na aula. Uma versão ampliada do método pode tratar essa recorrência, mas ela não faz parte do conteúdo utilizado nesta lista.

Recorrência D

Os parâmetros são:

a = 2
b = 2
f(n) = n²
p = log₂ 2 = 1

O expoente local é c=2c=2 e o expoente de referência é p=1p=1:

c>pc>p

É necessário verificar a regularidade:

2f(n2)=2(n2)22\cdot f\left(\frac{n}{2}\right)=2\left(\frac{n}{2}\right)^2 2n24=n222\cdot\frac{n^2}{4}=\frac{n^2}{2} n22=12f(n)\frac{n^2}{2}=\frac{1}{2}f(n)

Existe q=1/2<1q=1/2<1. Portanto, a regularidade é satisfeita e o caso 3 se aplica:

T(n)=Θ(f(n))=Θ(n2)T(n)=\Theta(f(n))=\Theta(n^2)

Decisão: usar o caso 3. O resultado é Θ(n2)\Theta(n^2).

Resposta: rejeitar o método nas recorrências A, B e C pelos motivos indicados. Na recorrência D, usar o caso 3 e obter Θ(n2)\Theta(n^2).

Exercício 12: decisão de engenharia com tempo e memória

Um sistema precisa ordenar 200000200\,000 registros por timestamp. Cada registro ocupa 4848 bytes. Registros com o mesmo timestamp devem preservar a ordem original.

Considere duas alternativas:

  • inserção: até n(n1)/2n(n-1)/2 comparações, espaço auxiliar Θ(1)\Theta(1) e ordenação estável;
  • intercalação: trabalho proporcional a nlog2nn\log_2 n, buffer auxiliar para nn registros e ordenação estável.

O sistema possui 1212 MiB disponíveis para o buffer. Use 1 MiB=10485761\text{ MiB}=1\,048\,576 bytes.

  1. Calcule o pior caso de comparações da inserção.
  2. Calcule nlog2nn\log_2 n aproximadamente. Use log220000017,61\log_2 200\,000\approx17{,}61.
  3. Calcule o buffer da intercalação em bytes e MiB.
  4. Verifique as restrições de estabilidade e memória.
  5. Escolha a alternativa e justifique com os valores calculados.
Solução

1. Pior caso da inserção

CI(n)=n(n1)2C_I(n)=\frac{n(n-1)}{2}

Substituindo n=200000n=200\,000:

CI(200000)=2000001999992C_I(200\,000)=\frac{200\,000\cdot199\,999}{2}

Primeiro, divida 200000200\,000 por 22:

CI(200000)=100000199999C_I(200\,000)=100\,000\cdot199\,999 CI(200000)=19999900000C_I(200\,000)=19\,999\,900\,000

O pior caso exige quase vinte bilhões de comparações no modelo fornecido.

2. Escala da intercalação

CM(n)nlog2nC_M(n)\approx n\log_2 n CM(200000)20000017,61C_M(200\,000)\approx200\,000\cdot17{,}61 CM(200000)3522000C_M(200\,000)\approx3\,522\,000

Esse valor representa a escala informada no enunciado. Ele não é uma contagem exata de todas as instruções da implementação.

3. Tamanho do buffer

Cada um dos 200000200\,000 registros ocupa 4848 bytes:

B=20000048B=200\,000\cdot48 B=9600000 bytesB=9\,600\,000\text{ bytes}

Convertendo para MiB:

B=96000001048576 MiBB=\frac{9\,600\,000}{1\,048\,576}\text{ MiB} B9,16 MiBB\approx9{,}16\text{ MiB}

Como 9,16<129{,}16<12, o buffer cabe na memória disponível.

4. Verificação das restrições

Estabilidade da inserção:      atendida
Estabilidade da intercalação:  atendida
Memória da inserção:           atendida
Memória da intercalação:       9,16 MiB < 12 MiB, atendida

As duas alternativas atendem à estabilidade. A intercalação também atende ao limite de memória.

5. Decisão

A comparação de escala fornece:

Inserção no pior caso:  19 999 900 000 comparações
Intercalação:               3 522 000 unidades proporcionais
Buffer da intercalação:         9,16 MiB
Memória disponível:             12 MiB

A intercalação possui crescimento Θ(nlogn)\Theta(n\log n), atende à estabilidade e seu buffer cabe na memória. A inserção economiza memória, mas seu pior caso quadrático é muito maior para a entrada fornecida.

Resposta: escolher a intercalação, considerando somente o modelo e as restrições declaradas no exercício.