MO417 - Prova I1

Enunciado distribuido na sala.

Gabarito e critérios de correção:

  1. A ordem certa é a seguinte, sendo que as duas primeiras podem ser intercambiadas pois são iguais:

    (lg n)lg n
    nlg lg n
    √ n
    2lg* n

    Justificativas podem ser dadas em todos os casos tomando o lg dos dois lados.

    A questão valia 2,5 pontos. O critério de correção foi: 1,0 ponto pela ordem correta, e mais 0,5 para cada justificativa aceita. Teve gente que colocou coisas do tipo "a função lg* n cresce tão lentamente que mesmo n sendo o número de móleculas no universo ..." mas sem aplicar lg ou log para compará-la com outra. Este tipo de argumentação não foi considerada suficiente.

  2. Esta questão era a mais difícil da prova. O método mestre não pode ser aplicado, pois a recorrência não satisfaz às condições (1), (2) nem (3) cobertas pelo método, já que n lg n não é Ω(n1+ε) para nenhum ε positivo.

    Então o remédio é montar a árvore de recursão. Esta árvore tem log3n níveis, sendo que o nível i tem 3i nós com trabalho total n lg(n/3i), exceto o último que é composto de n folhas com trabalho total n.

    Assim, a complexidade é dada pela fórmula:

    log3n - 1
    (n lg(n/3i))    + n
    i=0

    que, após expansão, dará O(n lg2n).

    Esta possibilidade pode ser verificada por substituição supondo T(n) ≤ (n lg2n)/(2 lg 3) + (n lg n)/2 + n. Uma alternativa para quem não quis ou não conseguiu fazer as contas do somatório até o fim seria esta verificação por substituição, ou outra que também funcionasse.

    O critério de correção nesta questão ligou-se à árvore de recursão. A fórmula final da complexidade valia 1,0 ponto, e suas duas componentes principais, a saber, a somatória dos níveis e a parcela devida às folhas, valiam 1,0 ponto cada. Além disso, foram dados 0,5 pontos para outras informações importantes, por exemplo, quem tentou fazer pelo teorema mestre e concluiu que ele não podia ser aplicado ganhou 0,5 por esta conclusão.

  3. A questão mais fácil da prova. Os heaps são:

    51, 38, 12, 20, 27, 11, 1, 10, 3, 6, 15, 2: heap original
    51, 40, 12, 20, 38, 11, 1, 10, 3, 6, 27, 2: após 15 → 40 e rearranjo
    40, 38, 12, 20, 27, 11, 1, 10, 3, 6, 2: após remoção do máximo e rearranjo

    O critério foi simples: cada heap exceto o original valia 1,0 ponto. Acho que ninguém errou o primeiro. Teve gente que errou o segundo porque não trocou com a última folha (2) para poder remover esta última folha e daí rearranjar, mas já removeu a raiz na maior e rearranjou. Como conseqüência, ficou uma árvore binária incompleta, faltando uma folha no lugar originalmente ocupado pelo 15.

  4. Esta questão também não foi fácil. Pouca gente acertou. A saída era bolar um novo algoritmo, não visto em aula, que vai trocando os registros no próprio arranjo A. Usa-se o fato de que a chave já é a posição final do registro. Uma solução nesta linha seria:

    1.  for i <- 1 to n do
    2.    while i <> A[i].key do
    3.      trocar A[i] <-> A[A[i]]
    

    O critério de correção foi o seguinte. Correção valia 1,0 ponto, rodar em O(n) valia 0,5 pontos e ser local (in place) valia 0,5 pontos. O 0,5 ponto restante ficava como bônus para quem conseguisse as três coisas.

    Teve gente que propôs o counting sort, que atende duas das condições mas não é local. Ganharam 1,5 pois está correto e roda em O(n). Teve gente que teve a ideia certa, porém escreveu um algoritmo semelhante à solução que demos acima, mas no lugar do while na linha 3 tinha um if. Infelizmente não funciona, como mostra o exemplo 3,4,2,1: acaba em 2,1,3,4, ou seja, não ordenado. Estes ganharam 1,5 porque considerei 0,5 no quesito "correção".

    Teve um colega que fez duas passagens, ou seja, o código acima com if, mas repetido duas vezes. Infelizmente também não funciona, como mostra o exemplo 5,6,7,8,3,4,2,1: acaba em 2,1,3,4,5,6,7,8, ou seja, não ordenado. Mas também ganhou 1,5 na questão.


MO417 Home

© 2009 João Meidanis