Häufigkeiten zählen und gruppieren
Verwenden Sie Counter und defaultdict, um Zeichenhäufigkeiten zu zählen, Anagramme nach sortiertem Schlüssel zu gruppieren und die häufigsten k Elemente zu finden.
Häufigkeiten zählen und gruppieren ist eine kostenlose Coding Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 3 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.
Häufigkeitszählung: Das zentrale Muster
Die Häufigkeitszählung gehört zu den vielseitigsten Mustern in Coding-Interviews. Indem Sie erfassen, wie oft jedes Element in einer Liste oder einem String vorkommt, können Sie Fragen zu Duplikaten, Anagrammen, häufigsten Elementen und gültigen Anordnungen in O(n)-Zeit beantworten – deutlich effizienter als die Alternative aus Sortieren und Durchlaufen mit O(n log n).
Counter und defaultdict(int) sind die Standardwerkzeuge von Python. Beide erstellen eine Zuordnung von Elementen zu ihrer Anzahl; Counter unterstützt zusätzlich arithmetische Operationen und most_common.
from collections import Counter
words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
freq = Counter(words)
print(freq) # Counter({'apple':3,'banana':2,'cherry':1})
print(freq['apple']) # 3
print(freq['grape']) # 0 (not KeyError)
print(freq.most_common(2)) # [('apple',3),('banana',2)]Gültiges Anagramm (LeetCode 242)
LeetCode 242 „Gültiges Anagramm“: Ermitteln Sie, ob zwei Strings Anagramme voneinander sind. Zwei Strings sind Anagramme, wenn sie dieselben Zeichenhäufigkeiten aufweisen. Vergleichen Sie ihre Counter-Objekte oder sortieren Sie beide Strings. Die Verwendung von Counter benötigt O(n), das Sortieren O(n log n). Der Counter-Ansatz ist optimal und bildet die Definition direkt ab.
from collections import Counter
def isAnagram(s, t):
return Counter(s) == Counter(t)
# Alternative: manual frequency array for lowercase letters only
def isAnagram_arr(s, t):
if len(s) != len(t):
return False
freq = [0] * 26
for c in s: freq[ord(c) - ord('a')] += 1
for c in t: freq[ord(c) - ord('a')] -= 1
return all(f == 0 for f in freq)
print(isAnagram('anagram', 'nagaram')) # True
print(isAnagram('rat', 'car')) # False
print(isAnagram_arr('listen', 'silent')) # TrueAnagramme gruppieren (LeetCode 49)
LeetCode 49 „Anagramme gruppieren“: Gruppieren Sie alle Anagramme in einer gegebenen Liste von Strings. Die zentrale Erkenntnis: Anagramme haben dieselbe sortierte Zeichenfolge. Verwenden Sie ein defaultdict(list), dessen Schlüssel das sortierte Tupel des Strings ist (Tupel sind hashbar). Jede Gruppe wird unter demselben Schlüssel gesammelt. Zeitaufwand: O(n × L log L), wobei L die maximale Stringlänge ist.
from collections import defaultdict
def groupAnagrams(strs):
groups = defaultdict(list)
for s in strs:
key = tuple(sorted(s)) # hashable canonical form
groups[key].append(s)
return list(groups.values())
print(groupAnagrams(['eat','tea','tan','ate','nat','bat']))
# [['eat','tea','ate'], ['tan','nat'], ['bat']]
# Alternative key: tuple of 26 character counts (O(L) not O(L log L))
def groupAnagrams_v2(strs):
groups = defaultdict(list)
for s in strs:
key = tuple(ord(c) - ord('a') for c in sorted(s))
groups[tuple(Counter(s)[chr(ord('a')+i)] for i in range(26))].append(s)
return list(groups.values())
Die k häufigsten Elemente (LeetCode 347)
LeetCode 347 „Die k häufigsten Elemente“: Geben Sie die k häufigsten Elemente zurück. Ein direkter Ansatz benötigt O(n log n): Zählen Sie die Häufigkeiten, sortieren Sie nach absteigender Häufigkeit und nehmen Sie die ersten k Elemente. Der optimale O(n)-Ansatz verwendet Bucket-Sortierung: Erstellen Sie Buckets, die nach der Häufigkeit (1 bis n) indiziert sind, legen Sie jedes Element in den Bucket seiner Häufigkeit und durchlaufen Sie anschließend die Buckets von der höchsten zur niedrigsten Häufigkeit, bis Sie k Elemente gesammelt haben.
from collections import Counter
def topKFrequent(nums, k):
freq = Counter(nums)
# Bucket sort by frequency
buckets = [[] for _ in range(len(nums) + 1)]
for num, count in freq.items():
buckets[count].append(num)
result = []
for i in range(len(buckets) - 1, -1, -1):
result.extend(buckets[i])
if len(result) >= k:
return result[:k]
return result
print(topKFrequent([1,1,1,2,2,3], 2)) # [1, 2]
print(topKFrequent([1], 1)) # [1]Zeichen nach Häufigkeit sortieren (LeetCode 451)
LeetCode 451 „Zeichen nach Häufigkeit sortieren“: Ordnen Sie einen String so um, dass die Zeichen in absteigender Reihenfolge ihrer Häufigkeit vorkommen. Zählen Sie die Häufigkeiten, sortieren Sie die Zeichen nach absteigender Häufigkeit und hängen Sie sie aneinander. Die Verwendung von most_common ist der klarste Ansatz in Python. Zeitaufwand: O(n log n) für das Sortieren der eindeutigen Zeichen nach ihrer Häufigkeit.
from collections import Counter
def frequencySort(s):
freq = Counter(s)
return ''.join(ch * count for ch, count in freq.most_common())
print(frequencySort('tree')) # 'eetr' or 'eert'
print(frequencySort('cccaaa')) # 'cccaaa' or 'aaaccc'
print(frequencySort('Aabb')) # 'bbAa' or 'bbaA'Aufgabenplaner (LeetCode 621)
LeetCode 621 „Aufgabenplaner“: Ermitteln Sie bei gegebenen Aufgaben und einer Abkühlzeit n die minimale Zeit, um alle Aufgaben abzuschließen. Die entscheidende Erkenntnis: Die häufigste Aufgabe bestimmt die Struktur. Ordnen Sie max_count Kopien der häufigsten Aufgabe mit (n) Lücken an. Die minimale Gesamtzeit = max((max_count - 1) * (n + 1) + num_tasks_with_max_count, total_tasks). Wenn genügend unterschiedliche Aufgaben vorhanden sind, um die Lücken zu füllen, beträgt die Leerlaufzeit 0.
from collections import Counter
def leastInterval(tasks, n):
freq = Counter(tasks)
max_count = max(freq.values())
# How many tasks share the max frequency
num_max = sum(1 for v in freq.values() if v == max_count)
# Minimum slots needed based on most frequent task
min_slots = (max_count - 1) * (n + 1) + num_max
return max(min_slots, len(tasks))
print(leastInterval(['A','A','A','B','B','B'], 2)) # 8
print(leastInterval(['A','A','A','B','B','B'], 0)) # 6
print(leastInterval(['A','A','A','A','B','B','B','C','C','D'], 2)) # 10Mehrheitsabstimmung mit Counter
LeetCode 169 „Mehrheitselement“: Ermitteln Sie das Element, das mehr als n/2-mal vorkommt. Boyer-Moore ist zwar die optimale Lösung mit O(1) zusätzlichem Speicherplatz, aber mit Counter.most_common(1) lässt sich das Problem direkt in O(n)-Zeit und mit O(n) Speicherplatz lösen. Wenn im Interview O(1) Speicherplatz gefordert wird, stellen Sie Boyer-Moore als weiterführende Lösung vor; wenn zusätzlicher Speicherplatz zulässig ist, ist Counter klarer.
from collections import Counter
def majorityElement_counter(nums):
freq = Counter(nums)
return freq.most_common(1)[0][0]
# Boyer-Moore O(1) space
def majorityElement_moore(nums):
candidate, count = None, 0
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
return candidate
nums = [2, 2, 1, 1, 2, 2, 2]
print(majorityElement_counter(nums)) # 2
print(majorityElement_moore(nums)) # 2Erstes eindeutiges Zeichen
LeetCode 387 „Erstes eindeutiges Zeichen in einem String“: Ermitteln Sie den Index des ersten Zeichens, das genau einmal vorkommt. Ansatz mit zwei Durchläufen: Im ersten Durchlauf erstellen Sie eine Häufigkeitszählung; im zweiten Durchlauf finden Sie das erste Zeichen mit der Anzahl 1. Zeitaufwand: O(n), Speicherplatz: O(1), da das Alphabet auf 26 Zeichen festgelegt ist.
from collections import Counter
def firstUniqChar(s):
freq = Counter(s)
for i, ch in enumerate(s):
if freq[ch] == 1:
return i
return -1
print(firstUniqChar('leetcode')) # 0 (l)
print(firstUniqChar('loveleetcode')) # 2 (v)
print(firstUniqChar('aabb')) # -1Teilarraysumme gleich K (LeetCode 560)
LeetCode 560 „Teilarraysumme gleich K“: Zählen Sie die Teilarrays, deren Summe k ergibt. Die Brute-Force-Lösung benötigt O(n²). Der O(n)-Ansatz: Führen Sie eine laufende Präfixsumme und eine Häufigkeitsmap der bisher gesehenen Präfixsummen. Für jede Position i entspricht die Anzahl der bei i endenden Teilarrays mit Summe k der Anzahl früherer Präfixsummen, die gleich (current_prefix_sum - k) sind. Initialisieren Sie die Map mit {0: 1}, um Teilarrays zu berücksichtigen, die bei Index 0 beginnen.
from collections import defaultdict
def subarraySum(nums, k):
freq = defaultdict(int)
freq[0] = 1 # prefix sum of 0 seen once (empty prefix)
prefix_sum = 0
count = 0
for num in nums:
prefix_sum += num
# How many earlier prefix sums allow a k-sum subarray ending here
count += freq[prefix_sum - k]
freq[prefix_sum] += 1
return count
print(subarraySum([1, 1, 1], 2)) # 2
print(subarraySum([1, 2, 3], 3)) # 2
print(subarraySum([1, -1, 1, -1, 1], 0)) # 4Counter-Arithmetik und Schnittmenge
Counter unterstützt arithmetische Operationen: + führt Zählwerte zusammen (addiert sie), - subtrahiert (begrenzt das Ergebnis auf 0), & nimmt das Minimum (Schnittmenge) und | nimmt das Maximum (Vereinigung). Diese Operationen vereinfachen Probleme wie „gemeinsame Zeichen in mehreren Strings finden“ oder „die minimale Anzahl von Zeichen entfernen, damit ein String ein Anagramm eines anderen wird“.
from collections import Counter
A = Counter('abccdd')
B = Counter('ccdde')
print('Add: ', dict(A + B)) # sum of counts
print('Subtract: ', dict(A - B)) # A - B, clipped at 0
print('Intersect:', dict(A & B)) # min of shared counts
print('Union: ', dict(A | B)) # max counts
# Min steps to make s anagram of t (LeetCode 1347)
s, t = 'leetcode', 'practice'
diff = Counter(t) - Counter(s)
print('Chars to add:', sum(diff.values())) # 5Zusammenfassung: Wann Sie Häufigkeitszählung verwenden sollten
Greifen Sie zur Häufigkeitszählung, wenn ein Problem Folgendes umfasst: zu prüfen, ob zwei Strings bis auf ihre Reihenfolge gleich sind (Anagramm), die häufigsten oder seltensten Elemente zu ermitteln, sicherzustellen, dass eine Sammlung die richtigen „Bestandteile“ enthält, oder ein Teilarray-/Substring-Problem in ein Präfixsummen-mit-Map-Problem umzuwandeln. Der entscheidende Punkt ist, dass die Reihenfolge innerhalb einer Gruppe keine Rolle spielt – nur die Anzahlen zählen.
Verwenden Sie aus Gründen der Klarheit immer Counter; wechseln Sie nur dann zu einem einfachen dict oder Array, wenn Sie eine feinere Kontrolle benötigen oder bei einem begrenzten Alphabet strikt O(1) Speicherplatz einhalten müssen.
Schnelltest
Testen Sie Ihr Verständnis der in dieser Lektion behandelten Konzepte aus Data Structures & Algorithms — Coding Interview Prep.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: Counter ermöglicht eine Häufigkeitszählung in O(n) mit most_common, arithmetischen Operatoren und Zugriffen mit dem Standardwert null, die Gruppierung nach einer kanonischen Form (sortiertes Tupel) löst das Gruppieren von Anagrammen in O(nL log L) und eine Präfixsumme mit Häufigkeitsmap reduziert das Problem der Teilarraysumme k von O(n²) auf O(n). Als Nächstes lösen wir das Problem der längsten aufeinanderfolgenden Sequenz und beschäftigen uns mit dem Entwurf eines LRU-Caches.
Häufig gestellte Fragen
Ist die Lektion „Häufigkeiten zählen und gruppieren“ kostenlos?
Ja — der vollständige Text von „Häufigkeiten zählen und gruppieren“ 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 „Häufigkeiten zählen und gruppieren“?
Verwenden Sie Counter und defaultdict, um Zeichenhäufigkeiten zu zählen, Anagramme nach sortiertem Schlüssel zu gruppieren und die häufigsten k Elemente zu finden. 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 3 von 4.
Wie lange dauert die Lektion „Häufigkeiten zählen und gruppieren“?
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
- Interna von Hash-Funktionen und Kollisionsbehandlung
- Two-Sum und seine vielen Varianten
- Häufigkeiten zählen und gruppieren
- Längste aufeinanderfolgende Sequenz und LRU-Cache