PAA - Listas de exercícios de 2007.1 (prof. Poggi)

Primeira lista de exercícios (paa071-l1.pdf)

Exercício 1

Do menor até o maior crescimento assintótico (na mesma linha são funções de crescimento semelhante):

(1)
\begin{eqnarray} \log{\log n} \\ \log n <=> \log n^2 \\ 1000 (\log n)^2 \\ \frac{n}{\log n} \\ 0.005 n^{0.000001} \\ 70n \\ 50n \log n \\ 10n^{\pi} 30 n^3 \log n <=> n^3 \log n + 90 n^2 \log n \\ (1.5)^{(\log n)^2} \\ n^{\log \log n} \\ \end{eqnarray}

Exercício 2

(a) $f(n) = n^2 + n => O(s(n) = n^2)$ e $g(n) = n^2 => O(r(n) = n^2)$
(b) $f(n) = n^2 => O(s(n) = n^3)$ e $g(n) = n => O(r(n) = n^3)$

Exercício 3

Exercício 4

(a)

Multiplicar(u, v, n) //multiplicar os numeros u e v, ambos de n bits

    Se n == 0, retornar 0 // caso base

    Dividir u em duas metades: a e b
    Dividir v em duas metades: c e d
    ac = Multiplicar(a,c,n/2)
    ad = Multiplicar(a,d,n/2)
    bc = Multiplicar(b,c,n/2)
    bd = Multiplicar(b,d,n/2)

    Retornar ac*2^n + (ad+bc)*2^(n/2) + bd

(b) Recorrência $T(n) = 4T(n/2) + O(n)$ (supondo que a multiplicacao por 2^n toma tempo n), logo complexidade $O(n^2)$

(c) Recorrência $T(n) = 3T(n/2) + O(n)$, complexidade $O(n^{\log{_2} 3})$

Exercício 5

(a) Como mostrar que $\lim_{n \rightarrow \inf}{ \frac{ (\log n)^{100} }{ n^{\epsilon} } } = 0$ ?
(b) $2^{n+1} = 2 \cdot 2^n = O(2^n)$, pois existem constantes a, b e $n_0$ tal que $a2^n+b \geq 2 \cdot 2^n$ para $n \geq n_0$
(c) Acho intuitivamente que a afirmação é verdadeira, mas não sei como justificar.

Exercício 6

(a) Se n é par, temos $T(n) = \frac{1}{4}(3n^2 + 14n - 16)$, se n é ímpar, temos $T(n) = \frac{1}{4}(3n^2 + 14n - 13)$.
(b) Se n é par, temos $T(n) = 3(2^{\frac{n-2}{2}} + 2^{\frac{n}{2}}) - 3$, se n é ímpar temos $T(n) = 2^{\frac{n+3}{2}} - 3$.
(c) $T(n) = 3^{n-1}$ - esse eu suei pra fazer, viu?

Exercício 7

Exercício 8

ContaMaior (no_heap, x, k)
    se (valor(no_heap) < x)
        numMaior++

    se (numMaior > k)
        retornar

    ContaMaior(esq(no_heap),x,k)
    se (numMaior > k)
        retornar
    ContaMaior(dir(no_heap),x,k)
variável global numMaior
numMaior = 0
ContaMaior(raiz_heap,x,k)
se (numMaior > k)
    retornar "NAO"
senão
    retornar "SIM"

Exercício 9

(a)

Ordenar C
Para cada elemento i de C, faça:
    fazer uma busca binária em C pelo elemento de valor x-i
    se existe o elemento x-i, retornar "SIM"
retornar "NAO"

(b)

A = primeiro_elemento(C), B = ultimo_elemento(C)
enquanto (A <= B) faça:
    se (A+B == x) retornar "SIM"
    senão se (A+B > X) B--
    senão A++;
retornar "NAO"

Exercício 10

MenorDist(P, ini, fim) // menor distancia do conjunto de pontos P[ini] ate P[fim]
    se (ini >= fim) retornar INFINITO
    meio = (ini + fim)/2
    menorEsq = menorDist(P,ini,meio), menorDir = menorDist(P,meio+1,fim)
    menorTotal = minimo entre menorEsq e menorDir

    // neste trecho, vamos pegar os resultados dos dois lados (esquerdo e direito),
    // que ja vieram ordenados pelo valor da coordenada Y e vamos juntar em uma nova lista ordenada
    // pelo valor da coordenada Y de cada ponto - procedimento semelhante ao mergesort
    criar um vetor de pontos A de tamanho fim-ini+1
    pEsq = ini, pDir = meio+1, c = 1
    enquanto (pEsq <= meio E pDir < fim) faça:
        ponto A[c] = ponto com menor Y entre P[pEsq] e P[pDir]
        incrementar o ponteiro do lado escolhido e o valor de c
    enquanto (pEsq <= meio) faça:
        A[c] = P[pEsq], pEsq++, c++
    enquanto (pDir < fim) faça:
        A[c] = P[pDir], pDir++, c++
    copiar A para P[ini]...P[fim]

    para cada ponto i em P, faça:
        Checar se a distância do ponto i para os 6 próximos pontos na lista é menor que o valor de "menor"
        Se for, atualizar "menor"
    retornar menor

Exercício 12

(a)

MaiorSeq[1] = 1
para i de 2 até N, faça:
    MaiorSeq[i] = 1
    para j de 1 até i-1, faça:
        se (valor[i] > valor[j])
            MaiorSeq[i] = maximo (MaiorSeq[i], MaiorSeq[j]+1)
retornar o maior valor encontrado em MaiorSeq

(b)

MaiorSeq[1] = Peso[1]
para i de 2 até N, faça:
    MaiorSeq[i] = Peso[i]
    para j de 1 até i-1, faça:
        se (valor[i] > valor[j])
            MaiorSeq[i] = maximo (MaiorSeq[i], MaiorSeq[j]+Peso[i])
retornar o maior valor encontrado em MaiorSeq

(c) Muito trabalhosa…
(d) Complexidade polinomial, $O(n^2)$
(e) Sim, tá lá o algoritmo…

Exercício 13

Ordenar as sequencias S1 e S2
P1 = 1, P2 = 1, PS = 1
Enquanto (P1 <= N e P2 <= N) faça:
    Se (S1[P1] == S2[P2]) faça:
        S[PS] = S1[P1]
        PS++, P1++, P2++
    Senão se (S1[P1] < S2[P2])
        S[PS] = S1[P1]
        PS++, P1++
    Senão
        S[PS] = S2[P2]
        PS++, P2++
Retornar S

Pior caso: $O( n \log n )$
O melhor caso depende do algoritmo de ordenação utilizado, podendo ser até $O(n)$

Exercício 14

Minimo(ini, fim, eps)
    vetor de pontos P[4] = { ini, (ini+fim)/3, 2*(ini+fim)/3, fim }
    Se (fim - ini >= 2 * eps) retornar (ini+fim)/2
    Achar o indice x do ponto em P que possui o menor valor [[$ F(P_i) $]]
    Se X == 0, retornar Minimo(P[0],P[1],eps)
    Se X == 3, retornar Minimo(P[2],P[3],eps)
    retornar Minimo(P[X-1],P[X+1],eps)

Recorrência: $T(n) <= T( 2*n/3 ) + O(1)$, logo $T(n) = O(log U)$

(b) Sim, pois o algoritmo depende somente do logaritmo de um dos valores da entrada

Exercício 15

(a) $\lceil \log_2{n} \rceil$
(b) Busca binária $O(log h)$, logo $O(\log \log n)$.

Exercício 16

Um pé no saco, resolver a equação $\sum_{i=1}^{n}{ \sum_{j=i+1}^{n}{ \sum_{k=1}^{j-i}{1} } }$

Exercício 19

Opa! Esse aqui enganou todo mundo! Na verdade, a equação toda $\sum_{k=0}^{n-1}{k \cdot 2^{n-k}}$ tem que ser calculada em tempo logaritmo em função da entrada N - qualquer algoritmo assintoticamente maior que isso será mais do que linear no tamanho da entrada (um algoritmo linear em função de N seria exponencial em relação ao tamanho da entrada!).
A equação pode ser desenvolvida assim:

(2)
\begin{eqnarray} \sum_{k=0}^{n-1}{k \cdot 2^{n-k}} \\ 2^n \cdot \sum_{k=0}^{n-1}{\frac{k}{2^{k}} \\ \end{eqnarray}

Digamos $S(n) = \sum_{k=0}^{n-1}{\frac{k}{2^{k}}$, temos então:

(3)
\begin{eqnarray} S(n) &=& \sum_{k=0}^{n-1}{\frac{k}{2^{k}} \\ S(n) &=& \frac{1}{2^1} + \frac{2}{2^2} + \cdots + \frac{n}{2^n} \\ 2 \cdot S(n) &=& 1 + \frac{2}{2^1} + \frac{3}{2^2} + \cdots + \frac{n}{2^{n-1}} \\ 2 \cdot S(n) - S(n) &=& 1 + \frac{1}{2^1} + \frac{1}{2^2} + \cdots - \frac{n}{2^n} \\ S(n) &=& 1 + \sum_{k=1}^{n-1}{ \frac{1}{2^k} } - \frac{n}{2^n} \end{eqnarray}

Como $\sum_{k=1}^{n-1}{ \frac{1}{2^k} }$ é uma progressão geométrica de razão $\frac{1}{2}$, podemos calcular seu valor utilizando uma equação fechada:

(4)
\begin{eqnarray} S(n) &=& 1 - \frac{n}{2^n} + \frac{ (\frac{1}{2})^n - 1 }{ \frac{1}{2} - 1 } \\ S(n) &=& 1 - \frac{n}{2^n} + 2 \cdot (1 - \frac{1}{2^n}) \end{eqnarray}

Resta então o problema de calcular o valor de $2^n$ em tempo, no máximo, logaritmico. Isso pode ser feito usando divisão e conquista (top-down), com a seguinte recorrência:

(5)
\begin{eqnarray} T(n) = T(n/2)^2 * 2 \mbox{se n impar} \\ T(n) = T(n/2)^2 \mbox{se n par} \end{eqnarray}

Feito isso, calculamos $2^n$ e então podemos calcular facilmente, em tempo constante, $S(n)$ e o resultado final.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.