Toets algoritmiek, ter afsluiting van de cursus algoritmiek Nijmegen – Utrecht – Delft Uitwerking versie 25 maart 2016 Theorievragen Alle subvragen zijn 1 punt waard, totaal zijn er 12 punten te verdienen voor de theorievragen. 1. Geef drie eigenschappen die typerend zijn voor een algoritme. Een algoritme heeft een goed omschreven resultaat, een uitkomst of een product, maaksel. Een algoritme bestaat uit een sequentie van instructies, die na elkaar gedaan worden (met controlestructuren). De instructies mogen maar één uitleg hebben, ze moeten eenduidig zijn. Het algoritme moet na eindige tijd klaar zijn, het mag niet oneindig lang duren. Een algoritme heeft een zekere complexiteit. “Een algoritme is de weergave van het inzicht in een probleem op zo’n manier dat de oplossing zonder enig inzicht verkregen kan worden.” - Prof.Dr. Cees Witteveen, oratie, 17 januari 2007 2. Algoritmen en datastructuren gaan hand in hand. Leg in eigen woorden uit waarom. Doe dit aan de hand van een voorbeeld. Ten eerste is de datastructuur bepalend voor de uitwerking van een algoritme. Het zoeken van een item in een ongesorteerde array vereist een ander algoritme dan een het zoeken van een item in een gesorteerde boom. Ten tweede, de complexiteit van een algoritme wordt daarmee mede bepaald door de datastructuur. Algoritmen worden efficiënter als een geschikte datastructuur voor de gegeven situatie wordt gekozen. 3. Er zijn verschillende paradigma’s voor algoritmen, waaronder: Divide & Conquer Greedy algoritme Dynamic Programming Network flow (niet behandeld in deze cursus) a. Geef een voorbeeld van een algoritme gebaseerd op Divide & Conquer. Merge-sort: hierbij wordt de verzameling in tweeën gedeeld. De beide deelverzamelingen worden gesorteerd (ook weer volgende het divide & conquer principe) en vervolgens samengevoegd. Ander voorbeeld is het Algoritme van Karatsuba: bij vermenigvuldiging van 2 getallen van n x n heb je normaal n2 vermenigvuldigingen nodig. Bijvoorbeeld 612 x 358 . Immers: 8x2, 8x1, 8x6, 5x2,5x1,5x6,3x2,3x1,3x6 = 9 vermenigvuld. Aanpak: splits de getallen in 100-tallen en de rest. 612 = 6 x 100 + 12 358 = 3 x 100 + 58 a = 6 x 3 = 18 d = 12 x 58 = 696 (honderdtallen x honderdtallen) (eentallen x eentallen) e = (6 + 12)(3 + 58) – d – a = 384 (tientallen x tientallen) 2 Antw = 18x100 + 384 x100 + 696 = = 219096 Er is hierdoor één stap minder aan vermenigvuldigen nodig. Insertion soort is niet gebaseerd op Divide & Conquer. b. Leg in eigen woorden uit wat de essentie is van een greedy algoritme? Een manier van uitleggen is als volgt. In een greedy algoritme wordt voor elke situatie steeds gekozen voor de meest opportune weg. Vergelijk het met de situatie van een bergwandelaar die zo snel mogelijk naar de top van de berg wil komen. Hij zal bij elke splitsing het pad nemen dat het steilst omhoog gaat. Waarmee niet is gezegd dat hij daarmee de snelste route omhoog vindt. Let op: een Greedy Algoritme hoeft dus niet altijd tot een optimale oplossing te leiden. Is Dijkstra’s algoritme een voorbeeld van Greedy? Ja, maar wel een hele slimme: greedy is dat in iedere iteratie het kortste pad wordt berekend voor de locatie die het dichtstbij het vertrekpunt ligt: er wordt niet verder vooruit gekeken. Hierdoor worden ook locaties bezocht/berekend die totaal de verkeerde kant opgaan. 4. a. Zet de volgende lijst op volgorde van langzaamst tot snelst oplopend. O (2n), O (n2), O (n!), O (n log n), O (log n), O (n) O (log n), O(n), O (n log n), O (n2), O (2n), O (n!) b. Wat is de complexiteit van de volgende algoritmen in termen van orde van grootte? I. Dijkstra’s algoritme voor het vinden van de beste oplossing van het handelsreizigersprobleem? Er zit een fout in de vraag: Dijkstra’s algoritme is voor het vinden van het kortste pad, niet voor het Traveling Salesman Problem (TSP). Voor Dijkstra geldt: Met een priority queue kan O(m + nlog n) worden. Weer een voorbeeld van relatie met datastructuur. Maar O (n2) rekenen we ook goed. Voor het TSP geldt dat er tot op heden geen ‘snel’ algoritme is bedacht, de orde van grootte van de complexiteit is O(2n). II. Sorteren op basis van bubblesort? III. Het snelst bekende sorteeralgoritme? O (n2) Mergesort heeft een orde van grootte voor complexiteit van O(n log n). Quicksort heeft een worst case die O(n2) is, maar toch is het in de praktijk vaak sneller dan merge sort. Zie ook: http://bigocheatsheet.com/ IV. Het Horspools-algoritme voor het zoeken van een string in een tekst? Dat is O(n), waarbij n de lengte van de tekst waarin moet worden gezocht. O (mn) mag ook, we gaan er vanuit dat de m (de lengte van het gezochte patroon) klein is en wegvalt tegen n (de lengte van de tekst). 5. Vergelijk de datastructuren lijst en array. Bedoeld worden een gelinkte lijst en een array. a. In welke datastructuur is het eenvoudiger een element in te voegen? In principe is dat voor een lijst eenvoudiger. Bij een array moeten alle achterliggende elementen worden verschoven. Bij een lijst is dat niet nodig, alleen de verwijzing van het voorliggende element moet worden aangepast. b. In welke datastructuur is het eenvoudiger te zoeken naar een element? Uitgaande van een ongesorteerde lijst/array maakt het niet veel uit. Alle elementen moeten worden langsgegaan. Voor een array kan dat iets efficiënter dan voor een list omdat bij een list steeds de referentie naar het volgende element moet worden bekeken, terwijl bij een array dat niet hoeft. Bij een gesorteerde lijst/array kan het zoeken naar een element sneller bij een array. Je kunt immers in het midden beginnen en op die manier de zoekruimte beperken, zoals je ook in een telefoon vaak in het midden begint. Bij een lijst kun je niet eenvoudig het midden bepalen. c. In welke datastructuur is het eenvoudiger een element te verwijderen? Dat is vergelijkbaar met het toevoegen van een element. De toets gaat op de volgende pagina verder! Toepassingsvragen Totaal zijn er 12 punten + 5 bonuspunten te verdienen voor de toepassingsvragen. Gegeven is het volgende probleem. Je krijgt een verzameling van n verschillende, gehele, positieve getallen en een getal S. Wat is de som van een deel van deze getallen die zo dicht mogelijk bij S komt, maar niet groter dan S is? (Gelijk aan S mag dus wel.) a) (5 punten) Geef een recursieve definitie voor een functie OPT met als argumenten een getal s en een deel van de getallen, geïdentificeerd door een index i. Deze functie OPT moet de som teruggeven van een deel van de getallen 1 t/m i die s zo dicht mogelijk benadert. Je mag de functie wiskundig opschrijven of met pseudocode. Dit is vergelijkbaar met een oplossing voor het knapsack probleem. OPT (i, s) is de maximum waarde die kan worden bereikt niet hoger dan s, voor alle getallen van 1 tot i. OPT (i, s) = 0 als i = 0 OPT (i, s) = OPT (i – 1, s) als getali > s OPT (i, s) = max { OPT (i-1, s), getali + OPT (i-1, s – getali) } anders b) (6 punten) Geef pseudocode van een iteratief algoritme dat gebruik maakt van dynamisch programmeren om de antwoorden op alle deelproblemen te berekenen en op te slaan. M <- Array[1..i][0..S] gevuld met 0 voor elke element for(i = 1,...,i) for(s = 0,...,S) if ( getali > s ) M[i][s] = M[i-1][s] else M[i][s] = max { M[i-1][s], getali + M[i - 1][s - getali] } return M[i][S] c) (1punt) Wat is de looptijd van dit algoritme? Die is O (iS), waarbij i het aantal getallen is en S het maximum. d) (5 punten) BONUSVRAAG Implementeer het algoritme in een taal naar keuze. Niet uitgewerkt