aboutsummaryrefslogtreecommitdiffhomepage
path: root/notes/theo1/exam.md
diff options
context:
space:
mode:
Diffstat (limited to 'notes/theo1/exam.md')
-rw-r--r--notes/theo1/exam.md335
1 files changed, 335 insertions, 0 deletions
diff --git a/notes/theo1/exam.md b/notes/theo1/exam.md
new file mode 100644
index 0000000..0b93ea1
--- /dev/null
+++ b/notes/theo1/exam.md
@@ -0,0 +1,335 @@
+---
+author: Marvin Borner
+date: "`\\today`{=tex}"
+lang: de-DE
+pandoc-latex-environment:
+ bem-box:
+ - bem
+ bsp-box:
+ - bsp
+ prob-box:
+ - prob
+ proof-box:
+ - proof
+ visu-box:
+ - visu
+toc-title: Inhalt
+---
+
+```{=tex}
+\newpage
+\renewcommand\O{\mathcal{O}} % IDK WHY
+```
+# Tricks
+
+- $\log_a(x)=\frac{\log_b(x)}{\log_b(a)}$
+
+# Big-O-Notation
+
+- $f\in\O(g)$: $f\le g$
+- $f\in\Omega(g)$: $f\ge g$
+- $f\in o(g)$: $f<g$
+- $f\in\omega(g)$: $f>g$
+- $f\in\Theta(g)$: $f=g$
+
+# Master Theorem
+
+Mit $T(n)=aT(\lceil n/b\rceil)+\O(n^d)$ für $a>0$, $b>1$ und $d\ge0$,
+ist
+$$T(n)=\begin{cases}\O(n^d)&d>\log_ba\\\O(n^d\log_n)&d=log_ba\\\O(n^{log_ba})&d<\log_ba\end{cases}$$
+
+# Bäume
+
+- Binary Höhe: $\log n$; Binary Anzahl: $\sum_{i=0}^h2^i=2^{h+1}-1$
+- Heap:
+ - `Heapify`: rekursiv swap bis Bedingung nicht verletzt:
+ $\O(\log n)$
+ - `Decrease`: erniedrigen, dann heapify auf node: $\O(\log n)$
+ - `Increase`: erhöhen, dann rekursiv mit parent swappen bis
+ bedingung nicht verletzt: $\O(\log n)$
+ - `ExtractMax`: Wurzel mit letzter leaf ersetzen, `heapify(root)`:
+ $\O(\log n)$
+ - `Insert`: Einfügen an nächster Stelle mit $-\infty$,
+ `Increase(x)` : $\O(\log n)$
+ - `Build`: Array irgendwie als Baum schreiben, `heapify` auf jedem
+ Knoten von unten nach oben: $\O(n)$
+- Priority queue: Als heap analog
+
+# Hashing
+
+- irreversible Reduzierung des Universums
+
+# Graphen
+
+- Adjazenzmatrix: $a_{ij}=1$ bzw Gewicht wenn Kante von $i$ nach $j$
+ - für dense
+- Adjazenzliste: array von Knoten mit Listen von ausgehenden Kanten
+ - für sparse
+- Sources: längste finishing time von DFS
+- Sinks: alle Kanten umdrehen, dann sources finden
+- SCC: DFS auf umgedrehtem Graph, startend bei ursprünglicher source
+ (`\textrightarrow`{=tex} SCC). Weiter bei restlichen Knoten (nach
+ absteigenden finishing times): $\O(V + E)$
+- Cycles: durch DFS wenn visited nochmal visited wird
+- Topological sort: no cycles; DFS und Knoten nach absteigenden
+ finishing times sortieren
+
+## DFS
+
+- $\O(V+E)$ bzw. $\O(V^2)$ für Matrix
+
+TODO: Anleitung schriftlich
+
+## BFS
+
+- gleich wie DFS nur queue statt stack
+- $\O(V+E)$ bzw. $\O(V^2)$ für Matrix
+- gut für shortest path, einfach jedes Mal distance updaten
+
+## Relaxation
+
+- anfangs alle $\infty$ außer Start
+
+```{=tex}
+\begin{lstlisting}
+function Relax(u,v)
+ if v.dist > u.dist + w(u, v)
+ v.dist = u.dist + w(u,v)
+ v.$\pi$ = u
+\end{lstlisting}
+```
+## Bellman-Ford
+
+- $(|V|-1)$-mal alle Kanten relaxen, dann noch einmal alle relaxen
+ (wenn sich was ändert, dann cycle): $\O(V\cdot E)$
+- in undirected muss in beide Richtungen relaxed werden
+- blöd für negative Gewichte
+- geht auch dezentral/asynchron, damit einzelne Knoten sich updaten
+ können
+
+## Dijkstra
+
+- gierig: nimmt einfach immer die nächstbeste Kante
+- $\O((V+E)\log V)$ mit min-priority Queues
+- für PPSP einfach stoppen wenn Knoten erreicht wurde (oder auch
+ bidirektional, dann besser)
+
+## Floyd-Warshall
+
+- besser für APSP (da Bellmand/Dijkstra je für jeden Vertex ausführen
+ müssten: $\O(V^2\cdot E...)$)
+- dreimal `for` für Matrix
+
+## A\*
+
+- wie Dijkstra, nur mit nächstem $d(s,u)+w(u,v)+\pi(v)$ statt
+ $d(s,u)+w(u,v)$ (Heuristik)
+
+## Kruskal
+
+- für MST
+- Kanten aufsteigend sortieren; je nächste Kante zu leerem Graph
+ hinzufügen solange kein Zykel entsteht
+- oder voll toll mit union-find: $\O(E\log V)$
+ - weil dann Zykelerkennung ez geht und so
+
+## Prim
+
+- für MST
+- bei random starten, dann immer nächstbeste Kante hinzufügen (Kreis
+ erweitert sich)
+- mit priority queue $\O(E\log V)$
+
+# Sortierung
+
+- **stabil**: wenn gleicher Wert am Ende gleichen Index
+ - selection: stabil
+ - insertion: stabil
+ - heap: instabil
+ - merge: stabil
+ - quick: stabil (out-of-place)
+ - counting: stabil (mit Listen als buckets)
+- Annahme: konstante Vergleiche
+
+## Selection
+
+- je kleinstes Element entfernen und in Ausgabe pushen: $\O(n^2)$
+
+## Insertion
+
+- je Element nach links bewegen bis es kleiner-gleich ist. Dann für
+ nächstes wiederholen: $\O(n^2)$ oder best-case $\O(n)$
+
+## Bubble
+
+- Paare von hinten durchgehen, je swappen wenn größer: $\O(n^2)$ oder
+ best-case $\O(n)$
+
+## Merge
+
+- List halbieren, rekursiv beide Listenhälften merge-sorten und
+ mergen: $\O(n\log n)$ weil Master-Theorem
+- merge sollte nicht kopieren (also doof in funktionalen Sprachen)
+
+## Heap
+
+- Heap aus Zahlen erstellen, je `ExtractMax` anwenden: $\O(n\log n)$
+ worst und best
+
+## Quick
+
+- je Pivotelement (e.g. Median) wählen, dann kleiner/größer
+ Pivot-Hälfte rekursiv zusammenfügen: $\O(n^2)$ oder best-case
+ $\O(n)$
+- durch random Pivotelement ist worst-case $\O(n\log n)$ zu erwarten
+
+## Counting
+
+- array mit buckets, sortieren nach Schlüsselwert; am Ende concat
+ ausgeben: $\O(K+n)$ - besser als vergleichsbasierte Algorithmen
+
+## Radix
+
+- Zahlen werden als Strings vom Ende aus durch Counting-Sort sortiert:
+ $\O(d(n+K))$ mit $d$ als Anzahl der Ziffern
+- block-based: je nochmal $x$ buckets
+
+## Bucket
+
+- Werte aus Intervall $[i/n,(i+1)/n[$ werden bucket $i$ zugeordnet;
+ dann jeden Bucket mit Insertion sortieren: $\O(n)$ oder worst-case
+ $\O(n\log n)$
+
+# Suchen
+
+## Binary
+
+- (Array sortiert); `A[n/2]` betrachten, entsprechend in
+ linker/rechter Hälfte weitersuchen: $\O(\log n)$
+
+## Exponential
+
+- Zweierpotenz-Indizes durchgehen, bei $q<2^i$ binary auf $2^{i-1}$
+ und $2^i$
+
+## Binary tree
+
+- links $\le$ parent, rechts $\ge$ parent: $\O(\log n)$
+- rekursiver tree-walk für sort: $\O(n)$
+- insert wird obv sehr unbalanced: $\O(n)$
+- delete einfach nächstbestes passendes Element als Substitution
+ suchen: $\O(n)$
+
+### AVL
+
+- LeftRotation/RightRotation für balancing von Subbäumen (TODO?)
+- insert/delete: $\O(\log n)$ da balancing $\O(1)$
+
+# Gier
+
+- einfach immer das nächstbeste nehmen (Heuristiken)
+- häufig nicht optimal, dafür effizient
+ - bei Knapsack bspw. doof
+ - für Dijkstra, Kruskal, Prim aber auch global optimal
+
+## Lokale Suche
+
+- bei zufälligem Wert starten, lokale Nachbarschaft betrachten.
+ Aufhören, sobald keine bessere Lösung in lokaler Nachbarschaft ist
+- mit unterschiedlichen Startwerten wiederholen
+- bei TSP durch swappen eigentlich not too bad (also für TSP obv)
+
+### Simulated annealing
+
+- am Anfang zu höherer Wahrscheinlichkeit auch schlechtere Lösungen in
+ lokaler Nachbarschaft betrachten (in Abhängigkeit der Differenz)
+- Wahrscheinlichkeit ist je $e^{-\Delta/T}$
+- eigentlich ganz cool, aber T muss halt passend gewählt werden
+
+# Dynamik
+
+- Lösen von Problemen durch Kombination der Teilproblemlösungen
+ (bottom-up vs. top-down)
+
+## Knapsack
+
+- Dieb\*in will möglichst viel stehlen hehe
+- Fälle: Objekt $j$ wird nicht eingepackt: $K(V,j)=K(V,j-1)$
+- Fälle: Objekt $j$ wird eingepackt: $K(V,j)=K(V-vol_j,j-1)+val_j$
+- bottom-up Array konstruieren mit beiden Fällen und je Maximum nehmen
+- top-down bspw. durch rekursive Memoization
+- damit $\O(n\cdot V_\text{total})$ (abhängig von
+ $V\implies\text{Skalierung siehe Approximationsalgorithmen}$)
+
+# Backtracking
+
+- bspw. toll bei Queen's problem
+- einfach backtracken im Lösungsbaum wenn Teillösung ungültig
+
+# Branch and Bound
+
+- bound: untere Schranke bestimmen und mit aktueller Lösung
+ vergleichen
+- bei TSP ist die untere Schranke bspw. das Gewicht des MST
+- verbessert nur durchschittliche Laufzeit
+
+# Approximationsalgorithmen
+
+- Algorithmus finden, der der tatsächlichen Lösung möglichst nahe
+ kommt
+- Güte von Approximation $A$ mit Instanz $I$ entsprechend
+ $\alpha_A=\max_I\frac{\mathrm A(I)}{\mathrm{OPT}(I)}$
+- Beispiele
+ - Set/Vertex cover
+ - TSP: Zusätzliche Annahme: Dreiecksungleichung. Dann ist lower
+ bound MST und upper bound zweifacher Graph Durchlauf unter
+ Verwendung der Dreiecksungleichung
+ - damit $\alpha_A\le2$
+ - Knapsack: Volumina skalieren und inten - Rundungsfehler ergibt
+ entsprechend $\alpha_A$
+
+# Line
+
+- $\sigma=\sigma_1,...,\sigma_m$ Sequenz unbekannter $\sigma$
+- `\texttt{opt($\sigma$})`{=tex} sind Kosten des besten offline
+ Algorithmus
+- `\texttt{A($\sigma$})`{=tex} sind Kosten des online Algorithmus für
+ $\sigma$
+- **c-kompetitiv**, wenn für $\sigma$ gilt
+ $A(\sigma)\le c\mathrm{opt}(\sigma)$
+
+## Buy-or-rent
+
+- Wie lange Skifahren? Leihen $50$, kaufen $500$ Euro.
+- $\sigma_i=1\implies\text{skifahren}$,
+ $\sigma_i=0\implies\text{nicht skifahren}$
+- $\frac{A(\sigma)}{c\mathrm{opt}(\sigma)}=\frac{50(t-1)+500}{50t}$
+ minimal für $t=10$
+ - also Ski kaufen nach 10 Tagen
+
+## List-update
+
+- move-to-front ist am besten
+
+## Dating
+
+- wie viele Dates bevor Entscheidung?
+- Kalibrierungsphase mit $t$ Personen; in Phase 2 entscheiden sobald
+ jemand besser als alle aus Phase 1
+- blabla $t=\frac ne$ also mit ca. 1/3 kalibrieren
+
+# Closest pair of points
+
+- brute-force ($\O(n^2)$) und sortieren ($\O(n\log n)$) beides nicht
+ optimal
+- divide and conquer: Raum rekursiv aufteilen, Abstand closest pair je
+ Seite: $\O(n\log n)$
+ - problem in der Mitte lässt sich 2d elegant lösen
+- randomisierte Lößung: $\sqrt{n}$ zufällige Punkte und paarweise
+ Abstände
+ - kleinster Abstand ist $\delta$
+ - Hashing, Würfel, blabla effizient (TODO?)
+
+# KD-Bäume
+
+TODO.