Escolar Documentos
Profissional Documentos
Cultura Documentos
ANÁLISE DE
ALGORITMOS
UNIDADE 4 – ALGORITMOS
GULOSOS E PROBLEMAS P E
NP
Autor: Thiago Nascimento Rodrigues
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
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 1/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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.
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?
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 2/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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.
2. retorna nulo
4. se k = A[meio] então
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 3/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
5. retorna meio
8. senão
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
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 4/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 5/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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).
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 6/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
3. C[i] ← 0
5. C[A[j]] ← C[A[j]] + 1
9. B[C[A[j]]] ← A[j]
11. retorna B
APLICABILIDADE
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 7/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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).
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];
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNLzf… 8/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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 : theta de êne].
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).
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
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 .
DESEMPENHO
Muitos algoritmos gulosos apresentam tempo de execução de
complexidade linear.
CORRETUDE
Muitas vezes é difícil descobrir se um algoritmo guloso proposto
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 10/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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).
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 11/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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.
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 terceira estraté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.
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 12/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
1. enquanto R ≠ ∅ faça
3. A ← A ∪ {i}
5. fim enquanto
6. retornar A
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 13/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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].
4.4 Problemas P e NP
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 .
Existem
algoritmos
para
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 15/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
Descrição resolvê-
Podem ser Não podem
los, mas
resolvidos ser resolvidos
demandam
eficientemente por nenhum
tempo
programa
inviável
computacional
Computáveis
Sim Sim Não
na teoria
Computáveis
Sim Sim/não Não
na prática
Encontrar todos os
Rota mais
erros
Exemplo curta em um Decriptação
de um programa
mapa
computacional
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”.
VOCÊ SABIA?
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 16/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
Ainda que para uma entrada de tamanho n = 10 [ #PraCegoVer : êne igual a dez], um
100
algoritmo demande um tempo 10 [ #PraCegoVer : dez elevado a cem] (a quantidade
100
10 [ #PraCegoVer : dez elevado a cem] é conhecida como um googol – origem do
100
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).
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
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
Dada uma
possível lista deum
construir m circuito
desigualdades
fechadolineares
em que com coeficientes
um viajante visite racionais
todas as
sobre n variáveis
cidades u
exatamente u única
uma [ #PraCegoVer
vez e :cujo
sequência de u índice
comprimento 1
total
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 18/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
sobre n variáveis
cidades u , …,
exatamente u [ #PraCegoVer : sequência de u índice 1
1 uma n única vez e cujo comprimento total
até u índice êne]
corresponda a, no(uma desigualdade
máximo, o valor delinear
k . é descrita da forma a 1 u 1 +
a u + … + a u ≤ b [ #PraCegoVer : de á índice um vezes u índice
2 2 n n
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 á
1 n
índice um até á índice bê, seguido de bê]), decidir se existe uma
atribuição de números racionais para as variáveis u , …, u [
1 n
#PraCegoVer : sequência de u índice um até u índice êne] que satisfaça
todas as desigualdades.
SOMA DE SUBCONJUNTO
Dados números naturais p , …, p e c [ #PraCegoVer : sequência de
1 n
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
k
que cá pertença ao subconjunto cá maiúsculo seja igual a cê].
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 maneira de
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ê].
CLASSE DESCRIÇÃO
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 20/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
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.
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
SAIBA MAIS
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 22/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
Referências bibliográficas
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 23/24
27/02/2023, 16:57 Unidade 4 - Análise de algoritmos
https://student.ulife.com.br/ContentPlayer/Index?lc=IyP2HINt7kgtyq4uw8F3sw%3d%3d&l=I7aJAzLzUh2p9R%2fLCcea3w%3d%3d&cd=bezNL… 24/24