Studijní materiály

V této sekci nalezneš odkazy na studijní materiály, které tě uvedou do základních principů pro řešení algoritmických úloh, které se mohou objevit ve FIKSu.

Budeme se hodně odkazovat do knihy Průvodce Labyrintem Algoritmů, která je volně dostupná elektronicky. U matematičtějších témat se odkážeme na matematika.cz a pro obecné definice na Wikipedii.

Základní pojmy

Když řekneme problém nebo úloha, tak máme na mysli slovní nebo matematický popis vstupu a chtěného výstupu. Například: vstup by mohl být jízdní řád autobusových linek po republice a odkud kam se chceme dostat, a chtěný výstup je seznam spojů s přestupy, který Tě dostane ze startu do cíle.

Algoritmus je popis postupu řešení, který by měl být dostatečně podrobný, aby podle něj čtenář dovedl ze vstupů zjistit správný výstup.

FIKS má za cíl, aby sis vyzkoušel(a) návrh algoritmů. Hlavní je slovní popis algoritmu, který jasně vysvětluje co a jak se provede. Druhá část by měla ukázat, že je algoritmus „rychlý“. A nakonec, pokud je algoritmus složitý, tak je navíc potřeba pořádně dokázat jeho správnost.


Následující materiály jsou uspořádané podle doporučeného pořadí čtení.

Lekce 1

  1. Co je to třídění? Pomalé třídění v O(n^2)
  2. Binární vyhledávání
  3. Kombinatorika - Variace, Permutace a Kombinace
  4. Úvod do grafů

Lekce 2

  1. Reprezentace grafů
  2. Prohledávání do šířky - BFS a počet kroků od začátku
  3. Rychlé třídění sléváním v O(n log(n))
  4. Základní datové struktury - Fronta, zásobník, prioritní fronta, množina a slovník
  5. Datová struktura pro hledání minima - Haldy
  6. Datová struktura pro (pomalé) hledání hodnoty a úpravu hodnot - Vyhledávací stromy
  7. Hledání nejkratší cesty - Dijkstrův algoritmus
  8. Klasifikace hran a Prohledávání do hloubky - DFS
  9. Artikulace a mosty
  10. Úvod do řetězců a abeced
  11. Hledání řetězce v textu - KMP

Lekce 3

  1. Prefixový součet
  2. Hledání řetězce v textu trochu jinak - Rabin-Karp (Hešování)
  3. Datová struktura pro spojování množin prvků - Union-Find
  4. Minimální kostry - Jarníkův algoritmus (Halda) a Kruskalův algoritmus (Union-Find)
  5. Základy práce s nepřesností (materiál chybí)
  6. Operace nad body, přímkami, úsečkami, kružnicemi, atd. (materiál chybí)
  7. Konvexní obálka
  8. Nejdelší vybraná rostoucí podposloupnost (Dynamické Programování)
  9. Rychlé hledání hodnoty a úprava hodnot - Vyvažované vyhledávací stromy

Následující materiály jsou rozdělené podle témat.

Práce s polem

Třídění

Pole je nejjednodušší způsob reprezentace dat. Základní operace nad polem je setřídění. Nejčastěji najdeme třídění jako knihovní funkci o které nepotřebujeme nic vědět, takže jen zavoláme sort(pole) a je hotovo. Co ale dělá funkce sort pod pokličkou? a jak rychle třídit miliony prvků?

Vyhledávání

Když máme setříděné pole, tak lze velice rychle zjistit jestli v něm je nějaká hodnota.

Další využití pole

Když chceme rychle sčítat prvky pole v daném rozmezí, tak lze pole předzpracovat a umožnit rychlé součty v O(1), potom ale už nepůjde rychle měnit prvky v poli. Pokud chceme mít rychlé součty i změnu prvků, je potřeba použít Intervalové stromy.

V polích lze hledat různé struktury. Jedna z nich je LIS, kde hledáme co nejvíce prvků pole (ne nutně sousedních) takových, že jsou rostoucí.

Matematika

Při hledání vhodného algoritmu se můžeme setkat s matematickým problémem, a tak je dobré mít znalosti základů Teorie čísel, Kombinatoriky a Modulární aritmetiky.

Teorie čísel

Z této hluboké studně znalostí se nám nejčastěji bude hodit vědět co to jsou prvočísla, jak je rychle najít a jejich zajímavé vlastnosti. Každé číslo lze rozložit na unikátní seznam prvočísel, tomu se říká faktorizace (např.: 12=2*2*3). Jak hledání prvočísel tak i faktorizace se dá pro čísla do milionu algoritmicky rozumně řešit.

Kombinatorika

Kombinace a Variace jsou základní pojmy pokud chceme spočítat počet možností jak něco vybrat. Blízké jsou i Permutace, které vyjadřují konkrétní způsob jak se prohází prvky pole.

Rychlé předpočítání kombinačních čísel lze udělat Pascalovým trojúhelníkem.

Modulární aritmetika

Kolik bude hodin za 15 hodin, když je teď 10? Odpověď není 25, ale 1. Důvod je ten, že hodnoty hodin se opakují stále dokola, po 23 je 0 a na hodnotu 24 se nikdy nedostaneme. Když si navíc zakážeme minuty a sekundy, dostaneme něco čím se zabývá Modulární aritmetika.

Pro náš příklad s hodinami je 24 tzv. Modulo. Základní operace (+,-,*) fungují stejně jako běžně, po nich musíme přičíst nebo odečíst násobek 24 a dostat výsledek do rozmezí 0 až 23, to budeme značit operací 'mod 24'. Pro dělení je potřeba více fantasie, protože 1/5 není 12 minut (minuty jsme si zakázali), chceme tedy najít hodinu H, pro kterou 5H=1 mod 24. Toto splňuje pětka, protože 5*5 je 25 a to je mod 24 přesně 1 hodina. Takovéto řešení existuje vždy, pokud je modulo prvočíslo, a umí ho najít Eukleidův algoritmus.

V mnoha programovacích jazycích budeme implementovat modulo jako zbytek po dělení M, které se často značí znakem procento (%), tj. 27%4 vyjde 3. Dávejme pozor, protože zbytek po dělení může vyjít záporný, tedy -13%5 bude -3, modulo je vždy nezáporné, -13 modulo 5 je 2.

Fiks úlohy: Toasty

Datové struktury

Celá řada problémů se dá vyřešit chytrým uložením dat. Potom lze nad daty provádět nejrůznější operace rychle. Následující seznam popisuje jaká datová struktura se dá použít na jaké operace.

Implementaci takovýchto struktur často nemusíme dělat sami, protože ty základní už bývají ve standardní knihovně. Například v c++ jsou vector, queue, deque, priority_queue, set, map, které z vyššího seznamu pokrývají Pole, Haldy a Vyvažované vyhledávací stromy. Přesto je dobré si tyto struktury naimplementovat, protože knihovní struktury nemůžeme moc upravovat, a neupravené nám občas nestačí.

Grafy

Pomocí grafů se dá dobře namodelovat celá řada běžných problémů. Jeden typický je hlednání nejkratší cesty. Grafy mají také mnoho vlastností, které umíme rychle detekovat a využít při tvorbě řešení.

Nejkratší cesty

Grafem lze jednoduše namodelovat mapa měst a cesty mezi nimi. Když cestám přidáme vzdálenost (tzv. váha hrany), dostáváme vážený graf, na kterém umíme rychle hledat nejkratší cestu.

Prohledávání grafu

Jednoduchým průchodem grafu lze zjistit celou řadu informací. Například artikulace a mosty jsou „slabá místa“ po jejichž odebrání se část grafu rozpadne.

Minimální kostry

Řešení problému hledání minimální kostry je více a každé z nich používá nějakou datovou strukturu ze sekce výše.

Řetězce

Vyhledávání v textu je nejtypičtější úloha pro toto téma. Lze řešit velice rychle a algoritmus není ani tak komplikovaný. Toto téma ale obsahuje i špeky jako hledání palindromů, hledání mnoha různých řetězců uvnitř textu a hledání nejdelšího společného podřetězce.

Geometrie

Z pohledu návrhu algoritmu není geometrie tak obtížné téma, lze jednoduše říct, že najdeme průnik úseček, kružnic, nebo třeba tečnu kružnice k bodu. Z pohledu implementace je ale geometrie nevděčné téma, protože všechny zmíněné operace není jednoduché naimplementovat a mají často mnoho speciálních případů.

Například průnik dvou kružnic zní jednoduše, ale může nastat 5 případů toho jak jsou kružnice vzájemně pozicované výsledek průniku mohou být 2 body, nebo také žádný bod. Dále, pokud póčítáme na reálných číslech, tak je počítač nedovede přesně reprezentovat, a vzniká chyba, která se výpočtem může zvětšit nad únosnou mez. Je tak potřeba vždy počítat s drobnou mírou nepřesnosti. I pro jednoduše znějící úlohy je implementace komplikovaná a proto je téma geometrie z pohledu implementace považované spíše za obtížnější.