Você está na página 1de 4

M392 – Construção e Análise de Algoritmos

Prof. Napoleão Nepomuceno


Lista 1

Instruções:

1. A atividade deve ser


realizada em dupla.
2. Resoluções iguais estão
sujeitas à anulação definitiva.
3. O prazo de entrega é até às
19:00 da terça-feira, dia 30 de
abril de 2024.
4. O aluno deve
obrigatoriamente saber
explicar cada exercício
entregue.
Exercício 1 - Suponha que dois algoritmos, A e B, resolvem um mesmo problema. Assuma ainda que o
tamanho das instâncias do problema é dado por um parâmetro n. Para cada item abaixo, assumindo-se n
suficientemente grande, indique se A é mais rápido que B para toda e qualquer instância, se B é mais
rápido que A para toda e qualquer instância, ou se não podemos inferir qual dos dois algoritmos é mais
rápido. Só serão pontuados os itens devidamente justificados. (12%)

(a) O algoritmo A consome tempo Ο(n4) e o B consome tempo Ω(n3).


(b) O algoritmo A consome tempo Ο(n2) e o B consome tempo Θ(n4).
(c) O algoritmo A consome tempo Ω(n) no pior caso e o B consome tempo Ω(n3 ) no pior caso.
(d) O algoritmo A consome tempo Ο(n2 lg n) no pior caso e o B consome tempo Ω(n3) no melhor caso.

Exercício 2 - Aplique o método mestre para resolver as seguintes recorrências. (12%)

(a) T(n) = 4T(n/3) + n2


(b) T(n) = 1T(n/8) + 1
(c) T(n) = 8T(n/2) + n2
(d) T(n) = 16T(n/4) + n2

Exercício 3 - Determine um limite assintótico (notação Θ) para os seguintes métodos.

(a) (12%)
def impressao(n):
num = 1
for i in range(1, n + 1):
for j in range(1, i + 1):
print(f"{num:2d} ", end=" ")
num += 1
print()

n = 10
impressao(n)

(b) (12%)

def impressao(n):
num = 1
for i in range(1, n*n + 1):
for j in range(0, n*n- i + 1):
print(f"{num:2d} ", end=" ")
num += 1
print()

n = 3
impressao(n)
Exercício 4 - Determine um limite assintótico adequado para os seguintes métodos.

(a) (12%)

def binary_search(arr, left, right, target):


if left > right:
return -1

mid = (left + right) // 2


if arr[mid] == target:
return mid
elif arr[mid] < target:
return binary_search(arr, mid + 1, right, target)
else:
return binary_search(arr, left, mid - 1, target)

# Test the binary_search function


arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
target = 7
index = binary_search(arr, 0, len(arr) - 1, target)

if index != -1:
print(f"Chave {target} encontrada na posicao {index}.")
else:
print(f"Chave {target} não encontrada.")

(b) (12%)

def karatsuba_multiply(x, y):


if x < 10 or y < 10:
return x * y

n = max(len(str(x)), len(str(y)))
half = n // 2

a, b = divmod(x, 10**half)
c, d = divmod(y, 10**half)

ac = karatsuba_multiply(a, c)
bd = karatsuba_multiply(b, d)
ad_bc = karatsuba_multiply(a + b, c + d) - ac - bd

return (10**(2*half) * ac) + (10**half * ad_bc) + bd

x = 1001003
y = 9876542

result = karatsuba_multiply(x, y)
print(f"{x} x {y} = \n{result}")
Exercício 5 - Seja um vetor A de n elementos inteiros. É possível determinar a quantidade de elementos
ímpares do vetor em Θ(n), percorrendo-se o vetor de forma iterativa. Alternativamente, pode-se utilizar
um método de divisão-e-conquista. (a) Implemente uma função iterativa para determinar a quantidade de
elementos ímpares do vetor A. (4%) (b) Implemente uma função recursiva, baseada em divisão-e-
conquista, para determinar a quantidade de elementos ímpares do vetor A. O algoritmo recursivo deve
dividir o vetor em duas partes de tamanhos aproximadamente iguais até se chegar a um caso trivial.
(12%)

Exercício 6 - Dissertar sobre os algoritmos de ordenação (selection sort; bubble sort; insertion sort; e
merge sort), explicando as estratégias de resolução e discutindo as complexidades de melhor e pior casos.
(12%)

Você também pode gostar