Spickzettel zur Mustererkennung
Ordnen Sie 15 häufige Problemsignale (sortiertes Array, alle Kombinationen benötigt, Wert unter einer Einschränkung maximieren usw.) den Algorithmusmustern zu, die sie am schnellsten lösen.
Spickzettel zur Mustererkennung ist eine kostenlose Coding Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Coding Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.
Das 60-Sekunden-Spiel zur Mustererkennung
In einem echten Vorstellungsgespräch haben Sie nach dem Lesen eines Problems ungefähr 60 Sekunden, um zu erkennen, welches algorithmische Muster anwendbar ist, bevor der Interviewer erwartet, dass Sie mit dem Programmieren beginnen. Dies ist die wichtigste Fähigkeit, die Sie entwickeln sollten — nicht Implementierungen auswendig zu lernen, sondern zu erkennen, zu welchem Werkzeug Sie greifen sollten.
Mustererkennung entsteht, indem Sie Problemsignale (Wörter und Einschränkungen in der Problembeschreibung) bekannten Algorithmusfamilien zuordnen. Sobald Sie das Muster erkannt haben, wird die Implementierung zu einer Aufgabe, bei der Sie eine Vorlage ausfüllen. Diese Lektion ist ein systematischer Spickzettel mit den 15 häufigsten Problemsignalen und den jeweils zugehörigen Mustern.
# The recognition process
recognition_steps = [
'1. Read the problem once fully (do not start coding)',
'2. Identify the data structure: array, string, tree, graph, matrix?',
'3. Identify the ask: find min/max, count ways, enumerate, detect cycle...?',
'4. Note the constraint: n<=20 (bitmask), sorted (binary search), DAG (topo sort)?',
'5. Map signal -> pattern',
'6. State the pattern and complexity to the interviewer before coding',
'7. Handle edge cases mentally before writing',
]
for step in recognition_steps:
print(step)Signal 1–3: Muster für Arrays und Strings
Die häufigsten Problemsignale für Arrays und Strings:
- Sortiertes Array + Zielwert finden → Binärsuche O(log n)
- Paar/Tripel finden, dessen Summe dem Zielwert entspricht → Zwei-Zeiger-Verfahren O(n) bei sortierten Daten, Hash-Map O(n) bei unsortierten Daten
- Längstes/kürzestes Teilarray/Substring, das eine Bedingung erfüllt → Sliding Window O(n)
- Maximale/minimale Summe eines zusammenhängenden Teilarrays → Kadane-Algorithmus O(n)
- Duplikate erkennen → Hash-Set O(n) oder Sortieren O(n log n)
Wenn das Array sortiert ist, sollten Sie immer zuerst eine Binärsuche in Betracht ziehen. Unsortiert + Zielsummensuche + O(n) bedeutet fast immer eine Hash-Map für die Suche nach dem Komplement.
# Quick recognition: array/string signals
signals = [
('Sorted array, find element', 'Binary search O(log n)'),
('Find two elements summing to K', 'Sort+two-ptr O(n log n) or hash O(n)'),
('Longest subarray with property P', 'Sliding window (variable size) O(n)'),
('Max sum contiguous subarray', 'Kadane algorithm O(n)'),
('Anagram/permutation check', 'Frequency map (Counter) O(n)'),
('Contains duplicate', 'Hash set O(n)'),
('Merge two sorted arrays/lists', 'Two pointers O(n+m)'),
('Rotate / shift array', 'Reverse trick O(n) in-place'),
('Next permutation', 'Find rightmost ascent + swap + reverse'),
('Maximum product subarray', 'Track max and min (handles negatives)'),
]
for signal, pattern in signals:
print(f'{signal:45s} => {pattern}')Signal 4–6: Muster für Bäume und Graphen
Problemsignale und Muster für Bäume und Graphen:
- Ebene für Ebene traversieren / kürzesten Pfad in einem ungewichteten Graphen finden → BFS mit Deque O(V+E)
- Alle Pfade erkunden / Zyklen erkennen / DFS-Reihenfolge → Rekursive oder iterative DFS O(V+E)
- BST + In-Order-Eigenschaften (k-tes Element, sortierte Reihenfolge) → In-Order-DFS O(n)
- Niedrigsten gemeinsamen Vorfahren finden → Rekursiver Abstieg mit Pfadverfolgung O(n)
- Zusammenhängende Komponenten / zwei Gruppen vereinigen → DSU O(n × alpha(n))
# Tree/graph signal recognition
tree_graph_signals = [
('Level-order / minimum depth / word ladder', 'BFS with deque'),
('All paths / path sum / all permutations tree', 'DFS recursive'),
('Cycle detection (undirected)', 'DFS with parent / DSU'),
('Cycle detection (directed) / course schedule', 'DFS three-color / Kahn topo sort'),
('Shortest path weighted graph', 'Dijkstra (non-neg) / Bellman-Ford (neg)'),
('All-pairs shortest path', 'Floyd-Warshall O(V^3)'),
('Topological order', 'Kahn BFS topo sort'),
('Min spanning tree', 'Kruskal (DSU) / Prim (heap)'),
('Dynamic connectivity / union-find', 'DSU path compression + union by rank'),
('Autocomplete / prefix search', 'Trie'),
('BST kth smallest / range sum', 'In-order DFS'),
]
for signal, pattern in tree_graph_signals:
print(f'{signal:50s} => {pattern}')Signal 7–9: Signale für dynamische Programmierung
DP-Signale sind am schwersten zu erkennen. Achten Sie auf folgende Schlüsselwörter:
- „Anzahl der Möglichkeiten, …“ → Zählende DP (Zählen der Teilproblemlösungen addieren)
- „Minimale/maximale Kosten, um … zu erreichen“ → Optimierungs-DP (Minimum/Maximum der Teilproblemlösungen wählen)
- „Kann … erreicht werden?“ (Machbarkeit) → Boolesche DP (ODER-Verknüpfung der Teilproblemlösungen)
- Teilproblem, das durch zwei String-Indizes definiert ist → 2D-DP (LCS, Edit-Distanz)
- Elemente unter einer Kapazitätsbeschränkung nehmen oder überspringen → Rucksack-DP
- Optimale Teilstruktur + überlappende Teilprobleme → Rekursionsbaum auf wiederholte Aufrufe prüfen → DP
# DP signal recognition
dp_signals = [
('Number of ways to climb stairs / decode string', '1D DP (Fibonacci-like)'),
('Minimum cost to reach end / coin change', '1D DP (greedy fails)'),
('Longest increasing subsequence', '1D DP O(n^2) or patience sort O(n log n)'),
('Longest common subsequence of two strings', '2D DP O(mn)'),
('Edit distance between two strings', '2D DP O(mn) (LCS variant)'),
('Partition array into two equal subsets', '0/1 knapsack boolean DP'),
('Fill knapsack with max value under weight limit', '0/1 knapsack optimisation DP'),
('Burst balloons / matrix chain multiplication', 'Interval DP'),
('Palindrome partitioning minimum cuts', 'Interval DP + prefix palindrome'),
('Rob houses in circle', '1D DP × 2 (linear sub-problems)'),
]
for signal, pattern in dp_signals:
print(f'{signal:55s} => {pattern}')Signal 10–12: Signale für Heap, Stack und Greedy
Signale für Heap-, monotone-Stack- und Greedy-Probleme:
- Top-K-Elemente / k-größtes oder k-kleinstes Element → Heap (Min-Heap für die K größten Elemente, Max-Heap für das k-kleinste Element) O(n log k)
- Streaming-Median → Zwei Heaps (Max-Heap der kleineren Hälfte + Min-Heap der größeren Hälfte)
- Nächstgrößeres/-kleineres Element → Monotoner Stack O(n)
- Rechteck mit der größten Fläche / Regenwasser speichern → Monotoner Stack O(n)
- Intervallplanung / Anzahl nicht überlappender Intervalle maximieren → Greedy (nach Endzeit sortieren)
# Heap / stack / greedy signals
heap_stack_greedy = [
('Top-K frequent elements', 'Min-heap size K: O(n log k)'),
('Kth largest in array', 'Max-heap pop K times: O(n + k log n)'),
('Streaming median', 'Two heaps (max + min): O(log n) per insert'),
('Merge K sorted lists', 'Min-heap of (val, list_idx): O(n log k)'),
('Next greater element', 'Monotonic decreasing stack: O(n)'),
('Largest rectangle in histogram', 'Monotonic increasing stack: O(n)'),
('Sliding window maximum', 'Monotonic decreasing deque: O(n)'),
('Trapping rain water', 'Two pointers OR monotonic stack: O(n)'),
('Jump game reachability / minimum jumps', 'Greedy range expansion: O(n)'),
('Merge overlapping intervals', 'Sort by start, linear scan: O(n log n)'),
('Gas station circular', 'Greedy: start from reset point: O(n)'),
('Task scheduler with cooldown', 'Greedy: sort by frequency: O(n log n)'),
]
for signal, pattern in heap_stack_greedy:
print(f'{signal:45s} => {pattern}')Signal 13–15: Backtracking und Bitmanipulation
Signale für Backtracking und Bitmanipulation:
- Alle Teilmengen / Permutationen / Kombinationen erzeugen → Backtracking O(2^n oder n!)
- Bedingungen erfüllen (N-Damen, Sudoku) → Backtracking mit Beschneidung
- Ein fehlendes/eindeutiges Element finden → XOR O(n), O(1)-Speicher
- Alle Teilmengen einer kleinen Menge aufzählen (n ≤ 20) → Aufzählung mit Bitmasken 2^n
- Gesetzte Bits zählen / auf Zweierpotenz prüfen → Bit-Tricks (n & (n-1))
- DP zur Zustandskomprimierung bei einer kleinen Menge → Bitmask-DP O(2^n × n)
# Backtracking and bit signals
bt_bit_signals = [
('Generate all subsets of array', 'Backtracking O(n * 2^n) / bitmask'),
('Generate all permutations', 'Backtracking O(n * n!)'),
('Combination sum with target', 'Backtracking with pruning'),
('Word search in grid', 'Backtracking DFS on grid O(m*n*4^L)'),
('N-queens placement', 'Backtracking with column/diag sets'),
('Find single unique element (all others x2)', 'XOR all: O(n) O(1)'),
('Missing number in 0..n', 'XOR or sum formula: O(n) O(1)'),
('Count set bits in n', 'n &= n-1 loop or DP O(n)'),
('Check power of two', 'n > 0 and n & (n-1) == 0'),
('Travelling salesman (n<=20)', 'Bitmask DP O(2^n * n^2)'),
('Number with max XOR in array', 'Trie on binary representation'),
]
for signal, pattern in bt_bit_signals:
print(f'{signal:50s} => {pattern}')Analyse der Einschränkungen: Was N Ihnen sagt
Die Einschränkung für die Eingabegröße n gibt direkt die akzeptable Zeitkomplexität — und damit die Algorithmusfamilie — vor:
- n ≤ 20: O(2^n) oder O(n!) akzeptabel — Bitmask-DP, Backtracking
- n ≤ 500: O(n³) akzeptabel — Floyd-Warshall, Brute-Force-DP
- n ≤ 5000: O(n²) akzeptabel — naive DP, quadratisches Sortieren
- n ≤ 10^6: O(n log n) erforderlich — Merge-Sort, Heap, Binärsuche
- n ≤ 10^8: O(n) erforderlich — Zwei-Zeiger-Verfahren, Sliding Window, lineare DP
Diese Analyse der Einschränkung sollte Ihr erster Schritt nach dem Lesen des Problems sein — noch bevor Sie sich für einen Algorithmus entscheiden.
# Constraint -> acceptable complexity -> algorithm family
complexity_map = [
('n <= 20', 'O(2^n) or O(n!)', 'Bitmask DP, backtracking/permutations'),
('n <= 500', 'O(n^3)', 'Floyd-Warshall, cubic DP, brute force'),
('n <= 5000', 'O(n^2)', 'Quadratic DP, bubble/insertion sort'),
('n <= 100000', 'O(n log n)', 'Merge sort, heap, binary search, topo sort'),
('n <= 1000000', 'O(n)', 'Linear DP, two pointers, sliding window, hash'),
('n <= 10^8', 'O(n) tight', 'Only simplest O(n) — no large constants'),
('n <= 10^18', 'O(log n) or O(1)', 'Math / number theory, binary search on answer'),
]
print(f'{'Constraint':15s} {'Complexity':15s} {'Algorithm Family'}')
print('-'*70)
for constraint, complexity, algorithms in complexity_map:
print(f'{constraint:15s} {complexity:15s} {algorithms}')Problem → Muster: Schnelle Übung
Üben Sie diese Zuordnung, bis sie automatisch erfolgt. Lesen Sie jede Problembeschreibung und identifizieren Sie das Muster, bevor Sie die Lösung ansehen. Schnelligkeit ist entscheidend — in einem Vorstellungsgespräch sollten Sie das Muster innerhalb von 60 Sekunden erkennen:
- „Gegeben sei ein sortiertes Array. Finden Sie heraus, ob zwei Elemente die Summe K ergeben.“
- „Gegeben sei ein Baum. Finden Sie den Durchmesser (den längsten Pfad zwischen zwei beliebigen Knoten).“
- „Gegeben seien n Aufgaben mit der Abklingzeit k. Finden Sie die minimale Anzahl an CPU-Intervallen.“
- „Gegeben sei ein String. Finden Sie den längsten palindromischen Substring.“
- „Gegeben seien die Zahlen 1..n, wobei eine fehlt. Finden Sie die fehlende Zahl.“
# Quick-fire pattern recognition answers
problems = [
('Sorted array: two elements sum to K',
'Two pointers (left from start, right from end): O(n)'),
('Tree diameter (longest path)',
'DFS returning (height, max_diameter) pair: O(n)'),
('Task scheduler with cooldown k',
'Greedy: (max_freq - 1)*(k+1) + count_of_max_freq: O(n log n)'),
('Longest palindromic substring',
'Expand around centre OR Manacher: O(n^2) or O(n)'),
('Missing number in 1..n',
'XOR all indices and values: O(n) O(1)'),
('Number of islands in binary grid',
'BFS/DFS flood fill counting connected components: O(m*n)'),
('Decode string like 3[a2[bc]] -> aaabcbcaabcbc',
'Stack to handle nested brackets: O(n)'),
('Valid parentheses [(){[]}]',
'Stack push open, pop+match on close: O(n)'),
]
for problem, solution in problems:
print(f'Q: {problem}\nA: {solution}\n')Warnsignale: Wenn Ihr Muster nicht funktioniert
Selbst erfahrene Entwickler wählen zunächst manchmal das falsche Muster. Erkennen Sie die folgenden Signale dafür, dass Ihr aktueller Ansatz falsch ist, und wechseln Sie den Ansatz:
- Ihr O(n²)-Ansatz besteht kleine Tests, führt aber bei großen Eingaben zu TLE → Sie benötigen eine Hash-Map, eine Binärsuche oder eine monotone Datenstruktur
- Ihr Greedy-Ansatz scheitert an einem Gegenbeispiel → Versuchen Sie es mit DP
- Ihr DP-Zustandsraum ist zu groß → Suchen Sie nach einem Greedy-Beweis oder einer intelligenteren Zustandsdefinition
- Ihre BFS liefert die falsche Antwort → Prüfen Sie, ob Sie statt BFS (ungewichtet) Dijkstra (gewichtet) benötigen
- Sie erhalten NullPointerExceptions → Fügen Sie vor der Implementierung Basisfälle und Prüfungen für Randfälle hinzu
# Red flags and recovery strategies
red_flags = [
('TLE on large n', 'Check complexity; switch from O(n^2) to O(n log n) or O(n)'),
('WA with greedy', 'Find a counter-example; switch to DP or prove exchange arg'),
('DP table huge', 'State compression (bitmask/rolling array) or different state'),
('BFS gives wrong shortest path', 'Check if edges have weights; use Dijkstra instead'),
('Stack overflow in recursion', 'Add memoisation or convert to iterative with explicit stack'),
('Off-by-one in binary search', 'Use half-open intervals [lo, hi); verify with 2-element test'),
('DSU wrong answer', 'Check 0-indexed vs 1-indexed; check union direction'),
('Backtracking TLE', 'Add pruning conditions; ensure undo step is correct'),
]
print('Pattern | Recovery')
print('-'*70)
for flag, recovery in red_flags:
print(f'{flag:40s} => {recovery}')Mustererkennung in Vorstellungsgesprächen kommunizieren
In Vorstellungsgesprächen zeigt das Ausformulieren Ihrer Mustererkennung Ihre Expertise und gibt dem Interviewer die Möglichkeit, Sie zu unterstützen, wenn Sie in die falsche Richtung gehen. Verwenden Sie die folgende Struktur:
- „Mir fällt auf, dass das Array sortiert ist, daher denke ich an eine Binärsuche …“
- „Das Problem fragt nach dem maximalen Teilarray, daher handelt es sich um ein klassisches Problem für den Kadane-Algorithmus …“
- „Wir benötigen alle möglichen Teilmengen, was auf Backtracking mit einem Rekursionsbaum hindeutet …“
- „Die Einschränkung n ≤ 20 sagt mir, dass 2^n = 1M akzeptabel ist; Bitmask-DP könnte also funktionieren …“
Nennen Sie nach dem Muster auch die Zeit- und Speicherkomplexität, bevor Sie auch nur eine Codezeile schreiben. Dadurch zeigen Sie, dass Sie bereits vor der Implementierung über Effizienz nachdenken.
# Interview communication template
def communicate_approach(problem, pattern, time_complexity, space_complexity, edge_cases):
print(f'Problem: {problem}')
print(f'Pattern: {pattern}')
print(f'Time: {time_complexity}, Space: {space_complexity}')
print(f'Edge cases to handle: {", ".join(edge_cases)}')
print()
# Example communications
communicate_approach(
problem='Find longest substring without repeating characters',
pattern='Sliding window with a set tracking current window characters',
time_complexity='O(n)',
space_complexity='O(min(n, alphabet_size))',
edge_cases=['empty string', 'all same characters', 'all unique characters']
)
communicate_approach(
problem='Given sorted matrix, find if target exists',
pattern='Binary search or staircase search (top-right corner): eliminate row or column each step',
time_complexity='O(m + n)',
space_complexity='O(1)',
edge_cases=['empty matrix', 'single element', 'target at corners']
)Ihr Vokabular für Mustererkennung erweitern
Der schnellste Weg, Mustererkennung zu entwickeln, besteht darin, Probleme in thematischen Blöcken zu lösen — nicht zufällig. Arbeiten Sie eine Woche lang ausschließlich an Sliding-Window-Problemen. Danach an Problemen mit zwei Zeigern. Anschließend an DP-Problemen. Wenn Sie 20 Probleme desselben Typs lösen, entwickeln Sie schnell die Intuition, dieses Muster auf Anhieb zu erkennen.
Schreiben Sie nach jedem Problem eine einzeilige „Musternotiz“: das Problemsignal und das dadurch ausgelöste Muster. Erstellen Sie Ihren eigenen Spickzettel. Nachdem Sie 200 Probleme in thematischen Blöcken gelöst haben, werden Sie ungefähr 90 % der Vorstellungsgesprächsprobleme in weniger als 30 Sekunden erkennen — die verbleibenden 10 % erfordern selbst für erfahrene Entwickler eine sorgfältige Analyse.
# Personal pattern note template
pattern_notes = [
{'signal': 'sorted array + two sum', 'pattern': 'two pointers', 'example': 'LC 167 Two Sum II'},
{'signal': 'longest X without repeating', 'pattern': 'sliding window + set', 'example': 'LC 3 Longest Substring'},
{'signal': 'max sum subarray', 'pattern': 'Kadane', 'example': 'LC 53 Max Subarray'},
{'signal': 'permutations/subsets', 'pattern': 'backtracking', 'example': 'LC 46 Permutations'},
{'signal': 'tree path sum', 'pattern': 'DFS with accumulator', 'example': 'LC 112 Path Sum'},
{'signal': 'course schedule', 'pattern': 'Kahn topo sort', 'example': 'LC 207 Course Schedule'},
{'signal': 'top-K elements', 'pattern': 'min-heap size K', 'example': 'LC 215 Kth Largest'},
]
print(f'{'Signal':40s} {'Pattern':30s} {'Example'}')
print('-'*90)
for note in pattern_notes:
print(f'{note["signal"]:40s} {note["pattern"]:30s} {note["example"]}')Kurzer Test
Testen Sie Ihr Verständnis der Konzepte von Data Structures & Algorithms — Coding Interview Prep aus dieser Lektion.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: Mustererkennung ordnet Problemsignale Algorithmusfamilien zu — ein sortiertes Array deutet auf Binärsuche hin, „alle Teilmengen“ auf Backtracking und „minimale Kosten“ auf DP, die Einschränkung n gibt die akzeptable Komplexität vor: n ≤ 20 erlaubt O(2^n), n ≤ 10^6 erfordert O(n log n) oder besser, und das Aussprechen des Musters und der Komplexität vor dem Programmieren zeigt Expertise und ermöglicht Feedback vom Interviewer. Als Nächstes setzen wir die Mustererkennung mit zeitlich begrenzten Probeinterview-Problemen in den Schwierigkeitsgraden „einfach“ und „mittel“ in die Praxis um.
Häufig gestellte Fragen
Ist die Lektion „Spickzettel zur Mustererkennung“ kostenlos?
Ja — der vollständige Text von „Spickzettel zur Mustererkennung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Coding Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Spickzettel zur Mustererkennung“?
Ordnen Sie 15 häufige Problemsignale (sortiertes Array, alle Kombinationen benötigt, Wert unter einer Einschränkung maximieren usw.) den Algorithmusmustern zu, die sie am schnellsten lösen. Du übst Coding Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Coding Interview Prep zu starten?
Keine Vorkenntnisse erforderlich. Coding Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Spickzettel zur Mustererkennung“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Coding Interview Prep-Lektion Code schreiben und ausführen?
Ja. Jede Coding Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Spickzettel zur Mustererkennung
- Zeitlich begrenztes Probeinterview: einfache und mittelschwere Aufgaben
- Umgang mit Sonderfällen und Kommunikation im Interview
- Durchläufe schwieriger Aufgaben: Word Ladder II und Alien Dictionary