Buscar

Unidade 4 - Análise de algoritmos

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 26 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 26 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 26 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 1/26
ANÁLISE DEANÁLISE DE
ALGORITMOS ALGORITMOS 
UNIDADE 4 – ALGORITMOSUNIDADE 4 – ALGORITMOS
GULOSOS E PROBLEMAS P EGULOSOS E PROBLEMAS P E
NP NP 
Autor: Thiago Nascimento Rodrigues Autor: Thiago Nascimento Rodrigues 
Revisor: Bruno Carreira Coutinho Silva Revisor: Bruno Carreira Coutinho Silva 
INICIAR
Introdução
Caro(a) estudante, 
Os modelos e estratégias que podem ser empregados tanto no projeto como na análise
de algoritmos são os mais variados possíveis. À medida que nos aprofundamos e
dominamos técnicas cada vez mais elaboradas, somos capazes de entender problemas
com níveis de complexidade avançados e, consequentemente, de propor soluções
computacionais mais precisas e eficientes. Por isso, o estudo de algoritmos já conhecidos
e que implementam diferentes abordagens constitui uma etapa relevante para
profissionais que se dedicam à atividade de construir soluções computacionais. 
Nesta unidade, vamos explorar um pouco mais dos algoritmos recursivos e perceber
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 2/26
como eles têm larga aplicabilidade em problemas reais. Expandindo o nosso estudo das
estratégias de ordenação de dados em memória, vamos conhecer um algoritmo que
explora uma abordagem completamente distinta das analisadas até agora. Além disso,
teremos a chance de fazer uma imersão em uma técnica de desenvolvimento de
algoritmos conhecida como gulosa, que é muito empregada em cenários profissionais.
Finalmente, vamos ter uma visão geral sobre as principais categorias que organizam os
problemas dentro da Ciência da Computação. 
4.1 Algoritmos com recorrência
Sequências, também conhecidas como funções de uma variável discreta, aparecem em
muitas aplicações em ciências da computação, em análise numérica e, naturalmente, em
matemática discreta. Muitas dessas aplicações estão enraizadas em problemas práticos
de engenharia, nos quais os sistemas têm um espaço de estados finito ou enumerável.
Outros cenários surgem quando os sistemas mudam de estado apenas em instantes
discretos de tempo. Uma recorrência é uma equação que descreve a evolução ou
comportamento de funções desse tipo (DOBRUSHKIN, 2010). Sob uma perspectiva mais
computacional, recorrências modelam procedimentos que fazem chamadas a si próprios –
os conhecidos algoritmos recursivos. 
 
Muitos algoritmos úteis levam a recorrências descritas por funções inteiras – funções
que manipulam estritamente números inteiros. Uma classe particular desses algoritmos
são aqueles baseados na estratégia de divisão e conquista. Algoritmos desse tipo
normalmente resolvem o problema dividindo-o em vários subproblemas que são
semelhantes ao original, mas têm tamanhos menores e, em seguida, resolvem os
subproblemas recursivamente. A abordagem de dividir e conquistar é uma abordagem de
cima para baixo, uma vez que a solução para uma instância de nível superior de um
problema é obtida descendo e obtendo as soluções para instâncias menores. O tempo de
execução desses algoritmos pode, muitas vezes, ser descrito por uma recorrência de
funções inteiras. 
VOCÊ SABIA?
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 3/26
Dois exemplos típicos de funções inteiras são as funções piso e teto . O piso de
um número real x (escrito como [ x ]) corresponde ao maior inteiro que é menor ou
igual a x . Por outro lado, o teto de um número real x (escrito como [ x ]) é o menor
inteiro que é maior ou igual que x . Ambas funções são amplamente utilizadas na
modelagem de algoritmos recursivos e na solução de equações de recorrência.
Um tradicional exemplo de algoritmo recursivo é a busca binária . A busca binária
funciona de modo distinto da tradicional busca sequencial em que cada item de um vetor
é examinado por vez e comparado com o item que está sendo procurado. Uma busca
binária é executada sobre um vetor previamente ordenado e, por isso, ele pode se valer
dessa condição para realizar uma operação de pesquisa mais eficiente. Se um vetor
contiver somente um elemento, o problema será simples. Caso contrário, a ideia básica
da busca binária é a de comparar o item sendo procurado com o item posicionado no
meio do vetor. Se forem iguais, a busca termina com sucesso. Se o elemento do meio for
maior que o elemento sendo procurado, o processo de busca será repetido na primeira
metade do vetor (porque esse item deve estar na primeira metade); caso contrário, o
processo será repetido na segunda metade. Importante observar que, toda vez que uma
comparação é feita, o número de elementos a pesquisar é cortado pela metade. Para os
vetores grandes, esse método é superior à busca sequencial na qual cada comparação
reduz o número de elementos a pesquisar em apenas um. Por causa da divisão do vetor a
ser pesquisado em duas partes iguais, esse método de busca ficou conhecido como
busca binária. O pseudocódigo a seguir apresenta o passo a passo de uma busca binária
sobre um vetor ordenado de n posições. 
Algoritmo busca binária 
Entrada : Um vetor A[0 ... n] ordenado e uma chave k a ser pesquisada e os índices min e
max correspondentes aos limites à esquerda e à direita, respectivamente 
Saída : O índice i tal que A[i] = k , se k for encontrado em A ; nulo, caso contrário.
1. se min > max então
2. retorna nulo
3. meio ← [[min + max]/2]
4. se k = A[meio] então
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 4/26
5. retorna meio
6. se k < A[meio] então
7. BuscaBinaria(A, min, meio – 1, k)
8. senão
9. BuscaBinaria(A, meio + 1, max, k)
[ #PraCegoVer: Algoritmo de busca binária, tendo na entrada um vetor de A com intervalo
de zero a n orderando e uma chave k a ser pesquisada e os índices mínimo e máximo
correspondentes aos limites à esquerda e à direita, respectivamente. Na saída, tem-se o
índice i tal que A de i é igual a k, se j for encontrado em A, ou nulo, caso contrário. Assim,
a linha um tem se min maior que max então; na linha dois, retorna nulo; na linha três,
meio com seta para a esquerda intervalo de min mais max dividido por dois; na linha
quatro, se k igual a A meio então; na linha cinco, retorna meio; na linha seis, se k menor
que A meio então; na linha sete, busca binária de A, min, meio, traço, um e k; na linha
oito, então; e na linha nove, busca binária de A, meio mais um, max e k.] 
Importante observar que a busca binária foi definida recursivamente de modo muito
natural. Se o item sendo procurado não for igual ao elemento do meio do vetor, as
instruções serão pesquisar um subvetor usando o mesmo método. Desse modo, o método
de busca é definido em termos de si mesmo com um vetor menor como entrada. A
garantia de que o processo terminará está no fato dos vetores de entrada ficarem cada
vez menores, e a busca em um vetor de um único elemento é definida de modo não
recursivo, já que o elemento do meio desse vetor é seu único elemento. 
VOCÊ SABIA?
Uma busca binária é executada sobre um vetor de elementos no qual os objetos
foram posicionados em determinada ordem. Por exemplo, um dicionário ou um
catálogo de telefones pode ser considerado um vetor, cujos elementos estão em
ordem alfabética ou a folha de pagamento de uma empresa pode estar
classificado pelo CPF dos funcionários. Quando queremos pesquisar um nome em
um catálogo de telefones, uma palavra em um dicionário ou determinado
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 5/26
Em termos da complexidade do algoritmo, vemos que a cada chamadarecursiva, o
tamanho do vetor é dividido pela metade, ou seja, o termo da recorrência que modela
essa chamada é dado por T(n) = 2T(n/2) [ #PraCegoVer : tê de êne igual a dois tê de êne
sobre dois]. Para fins de clareza, considerando vetores de tamanho 2 [ #PraCegoVer :
dois elevado a cá], onde k [ #PraCegoVer : cá] é um inteiro não negativo, temos que a
busca binária vai apresentar complexidade da ordem de Θ(log n ) [ #PraCegoVer : theta
do logaritmo êne].
Teste seus conhecimentos
Atividade não pontuada.
empregado em um arquivo de pessoal, o processo usado para encontrar o
elemento é comumente realizado por meio de uma busca binária.
k 
4.2 Ordenação de tempo linear com algoritmo counting sort 
A avaliação do custo-benefício entre tempo de execução e espaço demandando em
memória no projeto de algoritmos é um problema bem conhecido tanto para teóricos
quanto para profissionais de computação. Considere, por exemplo, o problema de
computar valores de uma função em muitos pontos do seu domínio. Se o tempo de
processamento for crítico, podemos pré-calcular os valores da função e armazená-los em
uma tabela. Isso é exatamente o que profissionais tiveram que fazer antes do advento dos
computadores eletrônicos, o que sobrecarregou as bibliotecas com grandes volumes de
tabelas matemáticas. Embora essas tabelas tenham perdido muito de seu apelo com o
uso generalizado de computadores eletrônicos, a ideia subjacente provou ser bastante útil
no desenvolvimento de vários algoritmos importantes para outros problemas. Em termos
um pouco mais gerais, a ideia é pré-processar a entrada do problema, no todo ou em
parte, e armazenar as informações adicionais obtidas para acelerar e resolver o problema
depois (LEVITIN, 2012). Essa estratégia é conhecida como aprimoramento de entrada
(do inglês, input enhancement ) e é base para o algoritmo de ordenação counting sort,
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 6/26
cujo funcionamento difere de todas as demais abordagens de ordenação em memória
estudadas. 
VOCÊ SABIA?
Os termos-padrão usados como sinônimos para a técnica de aprimoramento de
entrada são pré-processamento e pré-condicionamento. De modo surpreendente,
esses termos também podem ser aplicados a métodos que usam a ideia de pré-
processamento, mas sem o uso de espaço extra em memória. Assim, a fim de
evitar confusão, usamos “aprimoramento de entrada” como um nome especial
para a técnica de compensação de tempo por meio do uso de mais espaço
empregada no algoritmo counting sort.
O algoritmo counting sort assume que cada um dos n elementos de um vetor fornecido
como entrada é um número inteiro no intervalo 0 a k , para algum inteiro k . Quando k =
O(n) [ #PraCegoVer : cá igual a ó de êne], a ordenação é executada em um tempo Θ(n) [
#PraCegoVer : theta de êne]. Essa abordagem de ordenação determina, para cada
elemento de entrada x , o número de elementos menores ou iguais que x . Então, ele usa
essas informações para colocar o elemento x diretamente em sua posição no vetor de
saída. Por exemplo, se 17 elementos forem menores que x , então, x pertence à saída na
posição 18. Naturalmente, para lidar com a situação em que vários elementos têm o
mesmo valor, um ajuste precisa ser feito, já que não queremos colocá-los todos na
mesma posição (CORMEN, 2009). 
O pseudocódigo, a seguir, apresenta o passo a passo do algoritmo. Ele faz uso de um
vetor extra B para armazenar os valores ordenados do vetor A informado. Além disso, um
vetor C auxiliar é usado como armazenador temporário. Depois do laço das linhas 02-03
que inicializa todas as posições do vetor C com valor zero, o laço das linhas 04-05 realiza
uma inspeção em cada posição do vetor A . Para cada valor x armazenado em uma
posição j de A , ou seja, x = A[j] [ #PraCegoVer : xis igual á de jota], C[x] [ #PraCegoVer :
cê de xis] é incrementado de 1. Então, depois da linha 05, C[i] [ #PraCegoVer : cê de í]
contém o número de elementos de A que são iguais a i , para cada inteiro i = 0, 1, …, k [
#PraCegoVer : í igual a zero, um até cá]. 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 7/26
Algoritmo counting sort 
Entrada : Um vetor A de n inteiros com valores entre 0 e k – 1 ; 
Saída : Um vetor B contendo os elementos de A ordenados. 
1. Defina um novo vetor C[0 ... k]
2. para i ← 0 até k faça
3. C[i] ← 0
4. para j ← 1 até n faça
5. C[A[j]] ← C[A[j]] + 1
6. para i ← 1 até k faça
7. C[i]← C[i] + C[i – 1]
8. para j ← n até 0 faça
9. B[C[A[j]]] ← A[j]
10. C[A[j]] ← C[A[j]] – 1
11. retorna B
Características do counting sort
» Clique nas setas ou arraste para visualizar o conteúdo
Números com o mesmo valor aparecem no vetor de saída na mesma
ordem em que aparecem no vetor de entrada.
COMPARAÇÕES ENTRE CHAVES
O algoritmo não realiza qualquer comparação entre as chaves que estão
sendo ordenadas.LIMITE ASSINTÓTICO INFERIOR
Como o algoritmo não é baseado em um modelo de comparações, o
limite inferior de Ω (n log n) [ #PraCegoVer : ômega de êne logaritmo
êne] não se aplica a ele.
APLICABILIDADE
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 8/26
As linhas 06-06 do algoritmo determinam, para cada i = 0, 1, …, k [ #PraCegoVer : i igual
a zero, um até cá], quantos elementos de A são menores ou iguais a i . Para isso, ele
executa uma incremental sobre o vetor C . Finalmente, o laço das linhas 08-10 aloca cada
elemento A[j] [ #PraCegoVer : á de jota] em sua correta posição ordenada no vetor B . Se
todos os n elementos de A forem distintos, então, ao executar a linha 08, para cada A[j] [
#PraCegoVer : á de jota], o valor C[A[j]] [ #PraCegoVer : cê de á de jota] corresponde à
posição correta final de A[j] [ #PraCegoVer : á de jota] no vetor de saída B , uma vez que
existem C[A[j]] [ #PraCegoVer : cê de á de jota], elementos menores ou iguais a A[j] [
#PraCegoVer : á de jota]. Como os elementos podem não ser todos distintos, o valor de
C[A[j]] [ #PraCegoVer :cê de á de jota] é decrementado cada vez que um elemento com
valor iguala A[j] [ #PraCegoVer :á de jota] é alocado no vetor B. Decrementar C[A[j]] [
#PraCegoVer : cê de á de jota] ocasiona que o próximo elemento com valor igual a A[j] [
#PraCegoVer : á de jota], se existir, seja armazenado na posição imediatamente anterior
a A[j] [ #PraCegoVer : á de jota] no vetor de saída. 
A Figura 1 ilustra o funcionamento do algoritmo quando aplicado sobre um vetor de oito
posições e com valores inteiros menores ou iguais a cinco. A Figura 1(a) retrata o vetor A
e o vetor auxiliar C após a linha 05 do algoritmo. A Figura1(b) apresenta o estado do vetor
C após a linha 07. Nas Figuras 1(c) a 1(e), o vetor de saída B , assim como o vetor
auxiliar C , são apresentados após a primeira, segunda e terceira iterações,
respectivamente, do laço indicado nas linhas 08-10. O vetor B ordenado, contendo os
valores de A , é retratado na Figura 1(f).
Muito utilizado como procedimento auxiliar em outros algoritmos de
ordenação como o Radix Sort.
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 9/26
Figura 1 – Operações do counting sort sobre um vetor de 8 posições com valores inteiros menores ou iguais a 5. 
Fonte: CORMEN et al., 2009, p. 195. (Adaptado). 
Em termos de complexidade assintótica, temos as seguintes ordens para cada trecho do
algoritmo:
Laço das linhas 02-03: demanda um tempo Θ(k) [ #PraCegoVer : theta de cá];
Laço das linhas 04-05: demanda um tempo Θ(n) [ #PraCegoVer : theta de êne]; 
Laço das linhas 06-04: demanda um tempo Θ(k) [ #PraCegoVer : theta de cá]; 
Laço das linhas 08-10: demanda um tempo Θ(n) [ #PraCegoVer : thetade êne]. 
Portanto, o tempo total do algoritmo é da ordem de Θ(n + k) [ #PraCegoVer : theta de êne
mais cá]. Na prática, é comum empregar o counting sort quando o valor do maior número
é da ordem de O(n) [ #PraCegoVer : k igual a é de êne]. Nesse caso, o tempo de
execução é Θ(n) [ #PraCegoVer : theta de êne].
4.3 Algoritmos gulosos
De acordo com Kleinberg e Tardos (2006), é difícil, se não impossível, definir
precisamente o significado de algoritmo guloso. Ainda segundo os autores, um algoritmo é
dito guloso se ele constrói uma solução em poucos passos e toma uma decisão “míope”
em cada etapa, a fim de otimizar algum critério. Em outras palavras, um algoritmo guloso
faz uma escolha localmente ideal na “esperança” de que essa escolha o conduzirá a uma
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 10/26
solução globalmente ideal. Muitas vezes é possível projetar vários algoritmos gulosos
diferentes para um mesmo problema, cada um otimizando, em uma vizinhança restrita e
de modo incremental, alguma medida diferente em direção a uma solução.
Aspectos-chave das estratégias gulosas
» Clique nas abas para saber mais sobre o assunto
Cientistas da computação consideram o desenvolvimento de estratégias gulosas como
sendo uma técnica geral de projeto de algoritmos, apesar de ser aplicável apenas a
problemas de otimização. Via de regra, algoritmos gulosos são intuitivamente atraentes e
simples. Dado um problema de otimização, geralmente é fácil descobrir como proceder de
uma maneira gulosa, possivelmente depois de considerar algumas pequenas instâncias
do problema. O que é geralmente mais difícil é provar, quando possível, que um algoritmo
guloso produz uma solução ótima. Uma das maneiras comuns de demonstrar essa
corretude é por meio de indução matemática – mostramos que uma solução parcialmente
construída obtida pelo algoritmo guloso em cada iteração pode ser estendida para uma
solução ótima para o problema geral. Um segundo modo é mostrar que, em cada etapa, o
algoritmo se sai pelo menos tão bem quanto qualquer outro algoritmo faria no avanço em
direção à solução do problema (LEVITIN, 2012). 
 
Viabilidade Localmente ótima Irrevogável
VOCÊ SABIA?
Existem problemas para os quais uma sequência de escolhas localmente ideais
produz uma solução ideal para cada instância do problema em questão. No
entanto existem outros para os quais essa realidade não se mostra verdadeira;
para tais problemas, um algoritmo guloso ainda pode ser valioso se estamos
interessados em uma solução aproximada ou se podemos ficar satisfeitos com ela.
Cormen (2013) defende que o melhor modo de se entender a ideia por trás do projeto de
algoritmos gulosos é por meio da análise de exemplos que implementam estratégias
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 11/26
gulosas. Seguindo essa abordagem, um tradicional problema explorado nesse contexto é
o conhecido como escalonamento de intervalos ou escalonamento de recurso
(ROUGHGARDEN, 2019). Vamos considerar um conjunto de pedidos {1, 2... n} [
#PraCegoVer : conjunto composto pelos número um, dois até êne], onde a enésima
solicitação corresponde a um intervalo de tempo começando em s(i) [ #PraCegoVer :
ésse de í] e terminando em f(i) [ #PraCegoVer : éfe de í]. Um subconjunto de solicitações
é dito compatível se não houver qualquer sobreposição no tempo. O objetivo é aceitar o
maior subconjunto compatível possível. Conjuntos compatíveis de tamanho máximo são
chamados de conjuntos ótimos . 
Algoritmos gulosos – vantagens e desvantagens
» Clique nas setas ou arraste para visualizar o conteúdo
A ideia básica de um algoritmo guloso para o problema de escalonamento de intervalos é
usar uma regra simples para selecionar uma primeira solicitação i [ #PraCegoVer : í
índice um]. Uma vez que a solicitação i [ #PraCegoVer : í índice um] é aceita, todas as
demais solicitações que não são compatíveis com ela são rejeitadas. Em seguida,
selecionamos a próxima solicitação i [ #PraCegoVer : í índice dois] para ser aceita e,
novamente, rejeitamos todas as solicitações que não são compatíveis com i [
#PraCegoVer :í índice dois]. Continuamos assim, até que acabem todos pedidos. O
1 
1 
2 
2 
Para muitos problemas, é surpreendentemente fácil criar um ou vários
algoritmos gulosos que podem funcionar de forma satisfatória.
DESEMPENHO
Muitos algoritmos gulosos apresentam tempo de execução de
complexidade linear. CORRETUDE
Muitas vezes é difícil descobrir se um algoritmo guloso proposto
realmente retorna a saída correta para cada entrada possível. E mesmo
quando um algoritmo guloso está correto, provar sua corretude pode ser
difícil.
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 12/26
desafio em projetar um bom algoritmo guloso é decidir qual regra simples usar para a
seleção – e há muitas regras naturais para este problema que não geram boas soluções. 
Para exemplificar o desafio de se definir uma boa regra de escolha de pedidos, vamos
considerar três estratégias distintas. A regra mais óbvia pode ser sempre selecionar o
pedido disponível que começa primeiro – ou seja, aquele com tempo de início mínimo s(i)
[ #PraCegoVer : ésse de í], o que, por sua vez, faz com que o recurso comece a ser
usado o mais rápido possível. Esse método, entretanto, não produz uma solução ótima.
Se o primeiro pedido for de um intervalo muito longo, então, ao aceitar o pedido, podemos
ter que rejeitar muitos pedidos de intervalos de tempo mais curtos. Uma vez que o
objetivo é atender o máximo de solicitações possível, acabaremos com uma solução
abaixo do ideal. Em um caso muito ruim – por exemplo, quando o tempo de término f(i) [
#PraCegoVer : éfe de í] é o máximo entre todas as solicitações – a solicitação aceita
mantém o recurso ocupado por todo o tempo. Nesse caso, o método guloso aceitaria um
único pedido, enquanto a solução ideal poderia aceitar muitos. Essa situação é ilustrada
na Figura 2. 
Figura 2 – Instâncias do problema de escalonamento de intervalo em que algoritmos gulosos não conseguem
encontrar a solução ideal. 
Fonte: KLEINBERG; TARDOS, 2006, p. 117. (Adaptado). 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 13/26
Outra estratégia intuitiva seria a de começar aceitando a solicitação que requer o menor
intervalo de tempo – ou seja, a solicitação para a qual f(i) - s(i) [ #PraCegoVer : diferença
entre éfe de í e ésse de í] é o menor possível. Embora essa regra seja um pouco melhor
que a anterior, ela ainda pode produzir um escalonamento não ótimo. Por exemplo, na
Figura 2(b), a aceitação do intervalo mais curto ao meio impediria os outros dois, que
formam uma solução ótima, de serem aceitos. Fica claro que nessa segunda gulosa o
problema é que a segunda solicitação compete com a primeira e com a terceira, ou seja,
aceitar esse pedido acarretaria a rejeição dos outros dois pedidos. 
Desenvolvimento de algoritmos gulosos
» Clique nas abas para saber mais sobre o assunto
Tomando como base a segunda estratégia descrita, poderíamos criar um algoritmo guloso
com a seguinte abordagem de escolha de pedidos: para cada pedido, contamos o número
de outras solicitações que não são compatíveis e aceitamos a solicitação que tenha o
menor número de solicitações não compatíveis. Em outras palavras, selecionamos o
intervalo com o menor número de “conflitos”. Essa escolha gulosa levaria à solução ótima
no exemplo da Figura 2(b). No entanto, para uma instância do problema como
representado na Figura 2(c), a única solução ideal (aceitar as quatro solicitações na linha
superior) possível não seria obtida. Com essa terceiraestratégia gulosa, a solicitação do
meio na segunda linha é aceita o que garante uma solução de tamanho não superior a
três. 
Uma regra gulosa que leva à solução ótima é baseada em uma quarta ideia: devemos
aceitar primeiro o pedido que termina primeiro, ou seja, o pedido i para o qual f(i) [
#PraCegoVer : éfe de í] é o menor possível. Essa também é uma ideia bastante natural:
garantimos que o recurso fique disponível o mais rápido possível, enquanto ainda atende
a uma solicitação. Desse modo, é possível maximizar o tempo restante para atender a
outras solicitações. Para definir um algoritmo de modo mais formal, R será usado para
denotar o conjunto de solicitações que ainda não foram aceitas nem rejeitadas, e A vai
denotar o conjunto de solicitações aceitas. O pseudocódigo do algoritmo é apresentando
a seguir. 
 
Passo 1 Passo 2 Passo 3
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 14/26
Algoritmo escalonamento guloso 
Entrada : Um conjunto R de todas as requisições e um conjunto A vazio; 
Saída : Conjunto A com todas as requisições aceitas.
1. enquanto R ≠ ∅ faça
2. Escolha uma requisição i ∈ R com menor tempo para finalização
3. A ← A ∪ {i} 
4. Remova todas requisições de R que não sejam compatíveis com i
5. fim enquanto
6. retornar A 
Um exemplo de execução do algoritmo é ilustrado na Figura 3. Em cada etapa, o intervalo
selecionado está indicado com linhas mais escuras, e os intervalos excluídos na etapa
correspondente são indicados com linhas tracejadas.
Figura 3 – Exemplo de execução do algoritmo de escalonamento guloso. 
Fonte: KLEINBERG; TARDOS, 2006, p. 119. (Adaptado). 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 15/26
Em termos de implementação, o algoritmo guloso apresentado pode ser construído de
forma a funcionar com um complexidade da ordem O(n log n) [ #PraCegoVer : ó de êne
logaritmo de êne]. Primeiramente, é preciso ordenar as n solicitações de acordo com o
tempo para finalização e rotulá-las nessa ordem; ou seja, vamos assumir que f(i) < f(j) [
#PraCegoVer : éfe de í menor que éfe de jota] quando i < j [ #PraCegoVer : í menor que
jota]. Essa ordenação leva um tempo O(n log n) [ #PraCegoVer : ó de êne logaritmo de
êne] quando empregados algoritmos como quick sort (melhor caso) ou merge sort . Um
tempo O(n) [ #PraCegoVer : ó de êne] adicional será necessário para a construção de um
vetor S(1... n) [ #PraCegoVer : ésse maiúsculo de um até êne] com a propriedade de que
S(i) [ #PraCegoVer : ésse maiúsculo de í] contém o valor s(i) [ #PraCegoVer : ésse de í].
Feito isso, as requisições devem ser selecionadas processando-se os intervalos em
ordem crescente de f(i) [ #PraCegoVer : éfe de í]. O primeiro intervalo sempre deve ser
selecionado. Então, deve-se iterar por meio dos intervalos em ordem até atingir o primeiro
intervalo j para o qual s(j) ≥ f(1) [ #PraCegoVer : ésse de jota maior ou igual a éfe de um]
– este corresponderá ao próximo intervalo a ser selecionado. De modo mais geral, se o
intervalo mais recente que selecionamos terminar no tempo f , continuamos iterando pelos
intervalos subsequentes até chegarmos ao primeiro j para o qual s(j) ≥ f [ #PraCegoVer :
ésse de jota maior ou igual a éfe]. Desse modo, o algoritmo guloso analisado acima pode
ser implementado gastando um tempo constante por intervalo e fazendo com que esta
parte do algoritmo demande um tempo O(n) [ #PraCegoVer : ó de êne]. 
Teste seus conhecimentos
Atividade não pontuada.
4.4 Problemas P e NP
Diferentes algoritmos possuem uma ampla variedade de funções de complexidade de
tempo, e a caracterização de quais dessas funções são “suficientemente eficientes” e
quais são “muito ineficientes” sempre vai depender do problema a ser resolvido. No
contexto da computação, o conceito de problema está relacionado a uma questão geral
que precisa ser respondida e que frequentemente possui vários parâmetros ou variáveis
livres, cujos valores não são especificados. Logo, um problema pode ser descrito por uma
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 16/26
descrição geral de todos os seus parâmetros ou uma afirmação a respeito de qual
propriedade a resposta/solução deve satisfazer. De posse dessa definição, uma instância
de um problema é obtida por meio da especificação de valores particulares para todos os
parâmetros do problema. Um modo de se descrever como a solução para um dado
problema pode ser obtida consiste em apresentar um algoritmo para ele, ou seja, listar o
conjunto de passos que levam à geração da solução. Um algoritmo é dito capaz de
resolver um problema X se tal algoritmo pode ser aplicado a uma instância I de X e tem-se
a garantia que ele sempre produzirá uma solução para a instância I (GAREY; JOHNSON,
1979). 
Para vários problemas encontrados na literatura científica, já foram propostos algoritmos
capazes de encontrar soluções em tempo polinomial, ou seja, dada uma entrada de
tamanho n , o pior caso da complexidade de tempo é O(n ) [ #PraCegoVer : ó de êne
elevado a cá] para alguma constante k . Algoritmos que apresentam esse comportamento
assintótico são ditos tratáveis . Embora diversas técnicas já tenham sido desenvolvidas
para guiar a construção de algoritmos com essa ordem de eficiência, não é possível
afirmar que exista uma metodologia geral para a obtenção de procedimentos
computacionais eficientes para qualquer dado problema. Ao contrário, cada novo
problema que surge apresenta, em geral, desafios desconhecidos e que exigem a
proposição de novas estratégias para lidar com a dificuldade inerente a cada um (SEN;
KUMAR, 2019). Na prática, existem problemas para os quais os únicos algoritmos
capazes de solucioná-los demandam um tempo computacional inviável – à medida que o
tamanho da entrada cresce, o tempo requerido para se resolver o problema cresce a uma
taxa não polinomial (crescimento exponencial, fatorial etc.). Problemas dessa natureza
são ditos intratáveis . 
Apesar dessas duas classes de problemas (tratáveis e intratáveis) apresentarem uma
diferença determinante em relação à eficiência na obtenção de suas soluções, ainda
assim, problemas dessas duas categorias podem ser resolvidos por meio de algum
algoritmo computacional. Essa condição os classifica como problemas computáveis .
Outros sinônimos comuns para “computável” são “resolvível”, “decidível” e “recursivo”. Em
contrapartida, são problemas que não podem ser resolvidos por meio de um programa
executado por meio de um computador. Esses são ditos problemas incomputáveis . O
Quadro 1 apresenta uma visão esquemática de como os problemas na computação
podem ser classificados de acordo com a eficiência e viabilidade de implementação
k 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 17/26
computacional dos algoritmos capazes de resolvê-los. Nesse quadro, a marcação
“sim/não” na classe dos problemas incomputáveis indica que, para certos problemas
considerados intratáveis, não existe ainda uma prova formal de que são, de fato,
intratáveis.
Quadro 1 – As três maiores categorias de problemas computacionais
PROBLEMAS
TRATÁVEIS
PROBLEMAS
INTRATÁVEIS
PROBLEMAS
INCOMPUTÁVEIS
Descrição
Podem ser
resolvidos
eficientemente
Existem
algoritmos
para
resolvê-
los, mas
demandam
tempo
inviável
Não podem
ser resolvidos
por nenhum
programa
computacional
Computáveis
na teoria
Sim Sim Não
Computáveis
na prática
Sim Sim/não Não
Exemplo
Rota mais
curta em um
mapa
Decriptação
Encontrar todos os
erros 
de um programa
computacional
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=118/26
VOCÊ SABIA?
A máquina de Turing, proposta em 1936, é provavelmente o modelo para
formalização de algoritmos mais utilizado. De acordo com Diverio e Menezes
(2011), o trabalho de Turing foi “o primeiro a identificar programas escritos para
uma máquina computacional, com noções intuitivas de efetivamente computável”.
A máquina de Turing é um mecanismo usado para realização de cálculos e é
composto de: uma fita de tamanho infinito para armazenar dados, uma unidade de
controle capaz de realizar cálculos e um programa com comandos a serem
executados pela unidade de controle.
Um exemplo de problema dessa classe é conhecido como o problema da totalidade. Ele
consiste em decidir se uma máquina de Turing arbitrária é interrompida para qualquer
entrada passada para ela. Se existir um algoritmo capaz de tomar essa decisão, então, é
dito que ele calcula uma “função total”. Esse problema é equivalente ao problema de
determinar se um programa pode ou não entrar em um laço infinito para qualquer entrada
informada. Do mesmo modo, o fato do problema de a totalidade ser indecidível significa
que não é possível escrever um programa que seja capaz de encontrar qualquer laço
infinito em qualquer programa. 
Ainda que para uma entrada de tamanho n = 10 [ #PraCegoVer : êne igual a dez], um
algoritmo demande um tempo 10 [ #PraCegoVer : dez elevado a cem] (a quantidade
Fonte: Elaborado pelo autor, 2021.
Vários são os problemas (ou funções) que são decidíveis (ou computáveis), o que
significa que existe algum algoritmo que calcula uma resposta (ou saída) para qualquer
instância do problema (ou para qualquer entrada da função) em um número finito de
etapas simples. Por outro lado, também existem problemas e funções que são
indecidíveis ou incomputáveis, significando que não existe um algoritmo que possa
calcular uma resposta ou saída para todas as entradas em um número finito de passos.
Neste contexto, indecidível significa simplesmente incomputável dentro do escopo de um
problema de decisão cuja resposta (ou saída) é “sim” ou “não”.
100 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 19/26
10 [ #PraCegoVer : dez elevado a cem] é conhecida como um googol – origem do
nome “Google”), um problema que requer um tempo Θ(n ) [ #PraCegoVer : theta de
êne elevado a cem] é considerado como tratável. No entanto, na prática, poucos são os
algoritmos dessa ordem de complexidade. Em geral, os problemas da classe P exigem
muito menos tempo. Além disso, uma vez que um primeiro algoritmo de tempo polinomial
é encontrado para um problema, normalmente novos algoritmos ainda mais eficientes são
propostos subsequentemente (Cormen, 2013). 
Conforme já apresentado, cientistas da computação em geral consideram problemas
solucionáveis por algoritmos de tempo polinomial como “tratáveis” o que, de modo
informal, traz o significado de “fácil de lidar”. Um algoritmo é dito de tempo polinomial se o
seu tempo de execução no pior caso é limitado por um polinômio cujo grau é da ordem
das instâncias do problema. Mais formalmente, um algoritmo é polinomial se existe um
número i para todas as instâncias, tal que a complexidade de tempo do algoritmo é O(n )
[ #PraCegoVer : ó de êne elevado a í] onde n corresponde ao tamanho da instância.
Nesse sentido, se existir um algoritmo de tempo polinomial para um dado problema, esse
problema é dito como pertencente à classe P . 
VOCÊ SABIA?
Importante nunca confundir problemas da classe NP com problemas não
polinomiais. Um problema é dito NP se é verificável em tempo polinomial,
entretanto, ainda não foi encontrado um algoritmo que o resolva em tempo
polinomial. Por outro lado, problemas não polinomiais não se trata de problemas
para os quais não conhecemos um algoritmo polinomial, hoje, mas de problemas
que nunca terão um algoritmo polinomial. Problemas desse tipo são considerados
intratáveis (FORTNOW, 2009).
Há problemas, entretanto, que são verificáveis em tempo polinomial, mas para os quais
ainda não foram encontrados algoritmos polinomiais que os resolvam. Problemas desse
tipo são considerados como pertencentes à classe NP . Para resolver uma instância de
um problema desse tipo, o melhor que se pode fazer é testar todos os candidatos à
solução da instância. Outra característica desses problemas é a verificabilidade de suas
100 
100 
i 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 20/26
soluções. Supondo que uma solução seja proposta para um dado problema, deseja-se
verificar se a solução é correta ou não. Nesse sentido, outra característica de problemas
da classe NP é que, para todos eles, é possível realizar a verificação de uma solução
proposta em tempo polinomial. Uma solução apresentada para um problema NP é
chamada de certificado . Além disso, para que um problema seja considerado como NP,
o tempo para se verificar um certificado deve ser polinomial e da mesma ordem que o
tamanho da entrada do problema e do próprio certificado. 
Problemas NP
» Clique nas setas ou arraste para visualizar o conteúdo
índice í, jota] entre cada cidade e um número k qualquer, decidir se é
possível construir um circuito fechado em que um viajante visite todas as
cidades exatamente uma única vez e cujo comprimento total
corresponda a, no máximo, o valor de k .
PROBLEMA DE PROGRAMAÇÃO LINEAR
Dada uma lista de m desigualdades lineares com coeficientes racionais
sobre n variáveis u , …, u [ #PraCegoVer : sequência de u índice 1
até u índice êne] (uma desigualdade linear é descrita da forma a u +
a u + … + a u ≤ b [ #PraCegoVer : de á índice um vezes u índice
um mais á índice dois vezes u índice dois e isso somando até á índice
êne vezes u índice êne e essa soma menor ou igual a bê] para algum
conjunto de coeficientes a ,…, a , b [ #PraCegoVer : sequência de á
índice um até á índice bê, seguido de bê]), decidir se existe uma
atribuição de números racionais para as variáveis u , …, u [
#PraCegoVer : sequência de u índice um até u índice êne] que satisfaça
todas as desigualdades.
1 n 
1 1 
2 2 n n 
1 n 
1 n 
SOMA DE SUBCONJUNTO
Dados números naturais p , …, p e c [ #PraCegoVer : sequência de
pê índice um até pê índice êne e cê], decidir se existe um subconjunto K
de {1, …, n} [ #PraCegoVer : conjunto de um até êne] tal que a soma Σ (
p : k ∈ K ) seja igual a c [ #PraCegoVer : somatório de pê índice cá tal
que cá pertença ao subconjunto cá maiúsculo seja igual a cê].
1 n 
k 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 21/26
Naturalmente, se um problema pode ser resolvido em tempo polinomial, então, um
certificado para esse problema também pode ser verificado em tempo polinomial. Em
outras palavras, todo problema pertencente à classe P pertence automaticamente à
classe NP. O inverso, no entanto, constitui uma questão em aberto já por muitos anos.
Cabe ressaltar a importância de não se confundir problemas da classe NP com problemas
não polinomiais. De fato, até os dias atuais não foi encontrado, ainda, um único problema
NP provado que não esteja em P, ou seja, não foi identificado um problema que pode ser
verificado em tempo polinomial, mas para o qual não exista um algoritmo polinomial que o
resolva. Logo, a pergunta que padece de uma resposta formal é: todo problema cuja
solução pode ser verificada em tempo polinomial pode também ser resolvido por um
algoritmo polinomial? (KLEINBERG; TARDOS, 2006). 
Existe, ainda, outra classe de problemas que são considerados os mais difíceis dentre os
da classe NP. Eles são conhecidos como problemas NP-completos . Informalmente, um
problema é NP-completo se ele atende a duas condições: (1) está em NP e (2) se existir
um algoritmo de tempo polinomial para o problema, então, vai existir uma maneirade
converter todos os problemas da classe NP nesse problema, de modo a resolvê-los em
tempo polinomial. Logo, se existir um algoritmo de tempo polinomial para qualquer
problema NP-completo, ou seja, se houver algum problema NP-completo em P, pode-se
afirmar que P = NP [ #PraCegoVer : pê é igual a êne pê]. 
O Quadro 2 apresenta, de modo sintético, uma descrição das classes de computabilidade
nas quais os problemas podem ser agrupados. 
Quadro 2 – Classes de computabilidade 
CLASSE DESCRIÇÃO
P
Problema resolvível em tempo
polinomial com ordem correspondente
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 22/26
ao tamanho da entrada.
NP
Problema para o qual não se conhece
um algoritmo polinomial, isto é, dado
um certificado, é possível verificar em
tempo polinomial que o certificado é
uma solução para ele.
NP-difícil
Problema tal que, se existir um
algoritmo polinomial que o resolva,
então será possível converter todos os
problemas NP nele próprio de modo a
tornar possível que todo problema NP
seja resolvido em tempo polinomial.
NP-completo
Problema que é tanto NP-difícil como
NP.
Fonte: Elaborado pelo autor, 2021. 
Como os problemas NP-completos são os mais difíceis da classe NP, se houver algum
problema em NP que não é possível de ser resolvido em tempo polinomial, então,
nenhum dos problemas NP-completos são. Nesse contexto, outra classe de problemas é
conhecida como NP-difícil . Um problema é dito NP-difícil se ele satisfizer a segunda
condição de NP-completude, mas pode ou não estar em NP. A Figura 4 ilustra como as
diferentes classes estão relacionadas como conjuntos de problemas. 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 23/26
Figura 4 – Diagrama das classes de computabilidade supondo P contido em NP e diferente de NP. Fonte: Elaborado
pelo autor, 2021. 
Para concluir, destacamos que, como afirmam Diverio e Menezes (2011, p. 246), “o
objetivo do estudo da computabilidade é determinar a solucionabilidade de problemas, ou
seja, investigar a existência ou não de algoritmos que solucionem determinada classe de
problemas”. Por conseguinte, são investigados os limites da computabilidade e de sua
implementação, levando o estudo da solucionabilidade a não focar na pesquisa de
soluções inexistentes. 
Síntese
Nesta unidade, tivemos a oportunidade de explorar um pouco mais o conceito de
algoritmos recursivos. Vimos que as funções de recorrências constituem um poderoso
recurso matemático para modelagem de algoritmos desta classe. Além disso,
conseguimos explorar uma nova estratégia dentro do problema de ordenação de dados.
Por meio do detalhamento do algoritmo counting sort, vimos que é possível alcançar um
melhor desempenho computacional quando fazemos uso de mais espaço em memória. 
Com relação às estratégias disponíveis para fundamentar o projeto de algoritmos,
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 24/26
aprendemos como explorar uma abordagem conhecida como gulosa. A versatilidade
dessa estratégia dá margem para o desenvolvimento de um amplo espectro de algoritmos
que podem ser testados nos mais diversos cenários reais. Finalmente, o conceito de
computabilidade foi explorado e foi possível perceber que certos problemas não podem
ser resolvidos por meio de um algoritmo com número finito de passos. Esse mesmo
conceito foi adicionalmente abordado dentro das diferentes classes de problemas
existentes. Em decorrência dessa análise, uma das grandes questões que permanecem
em aberto dentro da Ciência da Computação, a saber P = NP? [ #PraCegoVer : pê igual a
êne pê?], também foi pontuada. 
SAIBA MAIS
Título : Algoritmos 
Autores : Sanjoy Dasgupta, Christos Papadimitriou e Umesh Vazirani 
 Editora : Bookman 
 Ano : 2010 
Comentário : Aproveite, primeiramente, o capítulo 5, em que a estratégia
de projeto de algoritmos gulosos é bem trabalhada. Mas não deixe de
explorar o capítulo 8, em que os conceitos relacionados a problemas P e
NP são igualmente bem analisados. 
 Onde encontrar : Biblioteca Virtual da 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 25/26
Título : Estruturas de dados: algoritmos, análise de complexidade e
implementações em Java e C/C++ 
 Autor : Ana F. Gomes Ascencio 
Editora : Pearson Prentice Hall 
Ano : 2010 
Comentário : Para se aprofundar nos conceitos relacionados a
recorrências, explore o capítulo 1, em que vários outros recursos
matemáticos são analisados dentro do contexto dessas funções. E, para
uma visão mais detalhada da busca binária considerada nesta unidade,
analise as seções finais do capítulo 2. 
Onde encontrar : Biblioteca Virtual da Laureate
Título : Métodos para análise de algoritmos 
 Autor(a) : Vladimir A. Dobrushkin 
Editora : LTC 
 Ano : 2012 
Comentário : Explore o capítulo 5, em que o conceito de recorrências é
apresentado sob uma perspectiva muito matemática. Nesse mesmo
capítulo, algumas aplicações são detalhadas e possibilitam ter uma visão
mais prática de como essas funções podem ser empregadas. 
Onde encontrar : Biblioteca Virtual da Laureate
Referências bibliográficas 
08/09/2022 22:02 Unidade 4 - Análise de algoritmos
https://codely-fmu-content.s3.amazonaws.com/Moodle/EAD/Conteudo/CTI_ANLALG_21/unidade_4/ebook/index.html?redirect=1 26/26
CORMEN, T. H. et al. Introduction to algorithms . 3.ed. Cambridge: MIT Press, 2009. 
CORMEN, T. H. Algorithms unlocked . 1. ed. Cambridge: MIT Press, 2013. 
DASGUPTA, S.; PAPADIMITROU, C.; VAZIRANI, U. Algoritmos . Porto Alegre: Bookman,
2010. 
DOBRUSHKIN V. A. Methods in algorithmic analysis , 1. ed. Boca Raton: CRC Press,
2010. 
DIVERIO, T. A.; MENEZES, P. B. Teoria da computação : máquinas universais e
computabilidade. 3. ed. Porto Alegre: Bookman, 2011. 
FORTNOW, L. The Status of the P Versus NP Problem. Communications of the ACM , v.
52, n. 9,p. 78-86, 2009. Disponível em: < https://cacm.acm.org/magazines/2009/9/38904-
the-status-of-the-p-versus-np-problem/fulltext >. Acesso em: 12 jan. 2021. 
GAREY, M. R.; JOHNSON, D. S. Computers and intractability : a guide to the theory of
NP-completeness. 1. ed. Nova Jersey: Bell Telephone Laboratories, 1979. 
KLEINBERG, J.; TARDOS, E. Algorithm design . 1. ed. Boston: Pearson Education,
2006. 
LEVITIN, A. Introduction to the design and analysis of algorithms . 3. ed. Boston:
Addison-Wesley,2012. 
ROUGHGARDEN, T. Algorithms illuminated – Part 3: greedy algorithms and dynamic
programming. 1. ed. San Francisco: Soundlikeyourself Publishing, 2019. 
SEN, S.; KUMAR, A. Design and analysis of algorithms : a contemporary perspective. 1
ed. Cambridge: Cambridge University Press, 2019.
https://cacm.acm.org/magazines/2009/9/38904-the-status-of-the-p-versus-np-problem/fulltext

Outros materiais