Um algoritmo ganancioso constrói uma solução um passo de cada vez, sempre escolhendo a opção que parece melhor agora - sem reconsiderar escolhas anteriores. Sem retrocesso, sem olhar para frente.
Funciona quando duas propriedades são válidas:
Dado um conjunto de atividades com horários de início e término, selecione o número máximo de atividades não sobrepostas.
Estratégia gananciosa: classifique por horário de término, sempre escolha a atividade que termina mais cedo.
def max_activities(intervals):
intervals.sort(key=lambda x: x[1])
count, end = 0, 0
for s, e in intervals:
if s >= end:
count += 1
end = e
return count
Por que isso funciona? Escolher a atividade que termina mais cedo deixa mais espaço para atividades futuras. Nenhuma outra escolha pode fazer melhor.
Crie um código binário ideal sem prefixo mesclando repetidamente os dois símbolos de frequência mais baixa. Isso é ganancioso: a cada passo, junte o par mais barato. O resultado é uma árvore onde símbolos frequentes recebem códigos curtos.
Dado um array onde nums[i] é o comprimento máximo do salto do índice i, determine se você pode alcançar o último índice.
Abordagem gananciosa: rastreie o índice mais distante acessível até o momento. Digitalize da esquerda para a direita - se você ficar para trás, retorne falso.
def can_jump(nums):
farthest = 0
for i, jump in enumerate(nums):
if i > farthest:
return False
farthest = max(farthest, i + jump)
return True
Entrar participar da discussão
No Jump Game, o que representa a variável gananciosa 'mais distante'?
Percorra uma rota circular com postos de gasolina. Na estação i você ganha gas[i] de combustível e gasta cost[i] para chegar à próxima estação. Encontre a estação inicial que permite completar o circuito ou retorne −1.
Insight ganancioso: se o gás total ≥ custo total, existe uma solução. Acompanhe um excedente corrente; sempre que cair abaixo de zero, a resposta deve começar após esse ponto.
Agende tarefas com um tempo de espera de n entre tarefas idênticas. Ganancioso: escolha sempre a tarefa restante mais frequente. A resposta depende da frequência máxima e de quantas tarefas a compartilham.
Tasks: A A A B B C, cooldown = 2
Schedule: A B C A B _ A
Total = 7
Mochila fracionária: você pode levar frações de itens. Ganancioso funciona - classifique por valor por peso, escolha primeiro a melhor proporção.
0/1 mochila: os itens são tudo ou nada. Ganancioso ** falha ** aqui porque pular um item pesado, mas valioso, pode ser pior do que pegar dois itens mais leves. Isso requer programação dinâmica.
Items: (weight=3, value=4), (weight=2, value=3), (weight=2, value=3)
Capacity: 4
Greedy (best ratio first): takes item 1 (w=3, v=4) → 1 remaining → can't fit rest → value = 4
Optimal: takes items 2+3 (w=4, v=6) → value = 6 ✗ Greedy fails!
Por que a abordagem gananciosa falha no problema da mochila 0/1?
✅ Funciona quando você pode provar a propriedade da escolha gananciosa:
❌ Falha quando os ótimos locais não se compõem nos ótimos globais:
A técnica padrão: assuma uma solução ótima que não use a escolha gananciosa. Mostre que você pode trocar uma de suas escolhas pela escolha gananciosa sem piorar a solução. Isso prova que ganancioso é pelo menos tão bom.
Para que é usado o 'argumento de troca'?
| Aspecto | Ganancioso | Programação Dinâmica | |--------|--------|---------------------| | Escolhas | Uma melhor escolha por etapa | Explore todos os subproblemas | | Revisita o passado? | Nunca | Sim - armazena subresultados | | Velocidade | Geralmente mais rápido | Depende do espaço de estados | | Correção | Somente se for provável | Sempre (se formulado corretamente) |
Em caso de dúvida, comece ganancioso - se não conseguir provar que funciona, mude para DP.