Memoiseren is een cruciale optimalisatietechniek die wordt gebruikt bij dynamisch programmeren om de efficiëntie aanzienlijk te verbeteren. Het werkt door de resultaten van dure functieaanroepen op te slaan en het in de cache opgeslagen resultaat terug te sturen wanneer dezelfde invoer opnieuw plaatsvindt. Dit vermijdt redundante berekeningen, wat leidt tot een dramatische versnelling, vooral bij problemen met overlappende subproblemen.
Hier ziet u hoe het wordt gebruikt:
1. Overlappende subproblemen identificeren: Dynamisch programmeren lost problemen op door ze op te splitsen in kleinere, overlappende subproblemen. Als hetzelfde deelprobleem meerdere keren wordt aangetroffen, kan het onthouden van een herberekening een herberekening voorkomen.
2. Resultaten opslaan: Om de resultaten van deelproblemen op te slaan, wordt gebruik gemaakt van een datastructuur, meestal een hashtabel (woordenboek in Python) of een array. De invoer voor het subprobleem (bijvoorbeeld de parameters van een recursieve functie) dient als sleutel, en het berekende resultaat is de waarde.
3. Controleren op in cache opgeslagen resultaten: Voordat het algoritme de oplossing voor een deelprobleem berekent, controleert het de opslag om te zien of het resultaat al beschikbaar is. Als dit het geval is, wordt het resultaat in de cache onmiddellijk geretourneerd.
4. Resultaten opslaan en retourneren: Als het resultaat niet in de cache wordt opgeslagen, berekent het algoritme het, slaat het op in de gegevensstructuur en retourneert het vervolgens.
Voorbeeld (Fibonacci-reeks):
Een naïeve recursieve oplossing voor de Fibonacci-reeks is zeer inefficiënt vanwege herhaalde berekeningen. Memoriseren verbetert dit drastisch:
Naïeve (inefficiënte) recursieve oplossing:
```python
def fibonacci_naïef(n):
als n <=1:
retour n
retourneer fibonacci_naïef(n-1) + fibonacci_naïef(n-2)
```
Gememoriseerde recursieve oplossing:
```python
memo ={} # Woordenboek voor memoisatie
def fibonacci_memo(n):
als n in memo:
retourmemo[n]
als n <=1:
resultaat =n
anders:
resultaat =fibonacci_memo(n-1) + fibonacci_memo(n-2)
memo[n] =resultaat
resultaat terug
```
In de gememoriseerde versie:
* 'Memo' slaat eerder berekende Fibonacci-getallen op.
* Voordat een recursieve aanroep wordt gedaan, controleert `fibonacci_memo` of het resultaat voor `n` al in `memo` staat.
* Als dit het geval is, wordt de opgeslagen waarde direct geretourneerd. Anders wordt het resultaat berekend, opgeslagen in 'memo' en vervolgens geretourneerd.
Deze verandering transformeert een exponentieel-tijdalgoritme in een lineair-tijdalgoritme. De sleutel is om de redundante berekeningen van dezelfde Fibonacci-getallen meerdere keren te vermijden.
In essentie: Memoiseren transformeert een top-down (recursieve) dynamische programmeerbenadering in een efficiëntere benadering door tussenresultaten in de cache op te slaan. Het vormt een aanvulling op tabelleringsbenaderingen (bottom-up), die ook redundante berekeningen vermijden, maar iteratieve methoden gebruiken in plaats van recursie. De keuze tussen memoiseren en tabelleren hangt vaak af van het specifieke probleem en de voorkeur van de programmeur; beide bereiken hetzelfde doel:het vermijden van redundante berekeningen. |