File: find-common-characters/solution.py

Date: 2026-06-06

Time: 16:36

Purpose

This file solves LeetCode 1002 — Find Common Characters. Given a list of strings, it returns every character that appears in all strings, including duplicates. For example, ["bella", "label", "roller"] returns ["e", "l", "l"] because e appears at least once in every word and l appears at least twice in every word.

It's one of ~400+ solutions in the leetcode-implementations repo, following the standard structure: solution.py + test_solution.py + review.md + plan.md.

Key Components

Solution.commonChars(self, words: List[str]) -> List[str] — the single method, matching LeetCode's expected signature. Takes a non-empty list of lowercase strings, returns a flat list of individual characters.

Patterns

The solution uses Counter intersection — a concise idiom for multi-set problems:

1. Seed common with the character frequencies of the first word.

2. For each remaining word, intersect (&=) with that word's frequencies. Counter._iand_ keeps the minimum count of each key across both counters.

3. common.elements() expands the final counter back into individual characters (e.g., Counter({'l': 2, 'e': 1})['l', 'l', 'e']).

This is the textbook approach for "characters common to all strings with multiplicity." The & operator on Counter objects does exactly what the problem asks for — no manual min-tracking needed.

Dependencies

Imports: collections.Counter (the workhorse) and typing.List (type annotation).

Imported by: The testsolution.py files listed in the "Imported By" section aren't actually importing *this* file — that list appears to be an artifact of the repo-wide test infrastructure. The direct consumer is find-common-characters/testsolution.py.

Flow


words = ["bella", "label", "roller"]

Step 1: common = Counter("bella")  →  {'b':1, 'e':1, 'l':2, 'a':1}
Step 2: common &= Counter("label") →  {'l':2, 'e':1, 'a':1, 'b':1} & {'l':2, 'a':1, 'b':1, 'e':1} = {'b':1, 'e':1, 'l':2, 'a':1}
Step 3: common &= Counter("roller") → {'b':1, 'e':1, 'l':2, 'a':1} & {'r':2, 'o':1, 'l':2, 'e':1} = {'e':1, 'l':2}
Step 4: list(common.elements())     → ['e', 'l', 'l']

Time complexity: O(n * k) where n is the number of words and k is the average word length. Space: O(1) since the counter is bounded by 26 lowercase letters.

Invariants

Error Handling

None. The code trusts the LeetCode contract (non-empty list of non-empty lowercase strings). An empty words list crashes; an empty string in words is handled correctly (intersection with an empty counter yields an empty counter).

Topics to Explore

Beliefs