ReviseAlgo Logo

Dictionaries

Counter

Specialized dictionary for counting hashable objects

Interview: Extremely common in interviews — anagrams, top-K, frequency analysis, and character problems

Last Updated: June 12, 2026 11 min read

Counter is a dict subclass from the collections module designed for counting hashable objects. It stores elements as keys and their counts as values, providing powerful methods for frequency analysis, multiset operations, and finding the most common elements. It's one of the most interview-friendly tools in Python.

Creating Counters

Counter can be initialized in multiple ways depending on your data source:

  • From iterable: Counter("abracadabra") or Counter([1, 2, 2, 3]) — counts each element
  • From dict: Counter({"a": 5, "b": 3}) — uses existing counts
  • From keyword args: Counter(a=5, b=3) — convenient for small counters
  • Empty Counter: Counter() — then update incrementally

Key Methods

  • most_common(n): Returns a list of the n most common (element, count) pairs. O(n log k) using a heap — very efficient
  • elements(): Iterator that yields each element repeated by its count — list(Counter("aab").elements()) → ['a', 'a', 'b']
  • update(iterable): Adds counts (doesn't replace) — c.update("aaa") adds 3 to count of 'a'
  • subtract(iterable): Subtracts counts — can produce zero or negative counts
  • Missing keys: Accessing a missing key returns 0 (not KeyError) — Counter is like defaultdict(int)

Counter as a Multiset

Counter supports multiset (bag) operations: addition combines counts, subtraction keeps only positive counts, intersection takes minimum counts, and union takes maximum counts. This makes Counter ideal for problems involving inventory, resource allocation, and frequency matching.

Arithmetic and Set Operations

  • Addition (+): Counter("aab") + Counter("abc") → Counter({'a': 3, 'b': 2, 'c': 1})
  • Subtraction (-): Keeps only positive results — Counter("aab") - Counter("abc") → Counter({'a': 1})
  • Intersection (&): Takes minimum of each — Counter("aab") & Counter("abc") → Counter({'a': 1, 'b': 1})
  • Union (|): Takes maximum of each — Counter("aab") | Counter("abc") → Counter({'a': 2, 'b': 1, 'c': 1})
  • Unary +/-: +c removes zero/negative counts; -c negates all counts

Common Interview Problems

  • Anagram check: Counter(s1) == Counter(s2) — O(n) vs sorting's O(n log n)
  • Top K frequent elements: Counter(nums).most_common(k) — the canonical solution
  • First unique character: Build Counter, then iterate string to find first with count == 1
  • Group anagrams: Use frozenset(Counter(word).items()) as grouping key
  • Minimum window substring: Use Counter to track required character frequencies

Counter vs defaultdict(int)

Both return 0 for missing keys, but Counter has extra methods: most_common(), elements(), update(), subtract(), and multiset operations. Use Counter when you need frequency analysis; use defaultdict(int) when you need general-purpose counting with custom logic.

Use Cases

Finding the most frequent elements (top-K problems)

Checking anagrams and character frequency matching

Inventory management and resource counting

Word frequency analysis in text processing and NLP

Multiset operations where elements can appear multiple times

Common Mistakes

Using sorted() + manual counting when Counter().most_common() is cleaner and more efficient

Forgetting that Counter.most_common() returns (element, count) tuples, not just elements

Not knowing that subtract() can produce negative counts — use - (subtraction operator) to keep only positives

Confusing update() (adds to counts) with dict.update() (replaces values) — Counter.update adds

Using Counter when a simple set suffices — Counter adds overhead for counting you may not need