Python Program to Group Anagrams from List
groups = defaultdict(list); for word in words: groups[''.join(sorted(word))].append(word).Examples
How to Think About It
Algorithm
Code
from collections import defaultdict def group_anagrams(words): groups = defaultdict(list) for word in words: key = ''.join(sorted(word)) groups[key].append(word) return list(groups.values()) words = ["eat", "tea", "tan", "ate", "nat", "bat"] print(group_anagrams(words))
Dry Run
Let's trace the list ['eat', 'tea', 'tan', 'ate', 'nat', 'bat'] through the code
Initialize groups dictionary
groups = {} (empty)
Process word 'eat'
sorted('eat') = 'aet'; groups = {'aet': ['eat']}
Process word 'tea'
sorted('tea') = 'aet'; groups = {'aet': ['eat', 'tea']}
Process word 'tan'
sorted('tan') = 'ant'; groups = {'aet': ['eat', 'tea'], 'ant': ['tan']}
Process word 'ate'
sorted('ate') = 'aet'; groups = {'aet': ['eat', 'tea', 'ate'], 'ant': ['tan']}
Process word 'nat'
sorted('nat') = 'ant'; groups = {'aet': ['eat', 'tea', 'ate'], 'ant': ['tan', 'nat']}
Process word 'bat'
sorted('bat') = 'abt'; groups = {'aet': ['eat', 'tea', 'ate'], 'ant': ['tan', 'nat'], 'abt': ['bat']}
Return grouped anagrams
[['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]
| Word | Sorted Key | Groups Dictionary |
|---|---|---|
| eat | aet | {'aet': ['eat']} |
| tea | aet | {'aet': ['eat', 'tea']} |
| tan | ant | {'aet': ['eat', 'tea'], 'ant': ['tan']} |
| ate | aet | {'aet': ['eat', 'tea', 'ate'], 'ant': ['tan']} |
| nat | ant | {'aet': ['eat', 'tea', 'ate'], 'ant': ['tan', 'nat']} |
| bat | abt | {'aet': ['eat', 'tea', 'ate'], 'ant': ['tan', 'nat'], 'abt': ['bat']} |
Why This Works
Step 1: Sorting letters creates a unique key
Sorting the letters of each word puts anagrams into the same order, so they share the same key.
Step 2: Dictionary groups words by sorted key
Using the sorted word as a dictionary key collects all anagrams together in a list.
Step 3: Return all grouped anagrams
The dictionary values are lists of anagrams, which we return as the final grouped result.
Alternative Approaches
def group_anagrams(words): groups = {} for word in words: key = tuple(sorted(word)) groups.setdefault(key, []).append(word) return list(groups.values()) words = ["eat", "tea", "tan", "ate", "nat", "bat"] print(group_anagrams(words))
from collections import defaultdict, Counter def group_anagrams(words): groups = defaultdict(list) for word in words: key = tuple(sorted(Counter(word).items())) groups[key].append(word) return list(groups.values()) words = ["eat", "tea", "tan", "ate", "nat", "bat"] print(group_anagrams(words))
Complexity: O(n * k log k) time, O(n * k) space
Time Complexity
Sorting each word of length k takes O(k log k), done for n words results in O(n * k log k).
Space Complexity
Extra space is used for the dictionary storing all words grouped by keys, up to O(n * k).
Which Approach is Fastest?
Using sorted strings as keys is simple and efficient; using Counters is slower due to counting overhead.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Sorted string keys | O(n * k log k) | O(n * k) | Simple and fast grouping |
| Tuple of sorted letters | O(n * k log k) | O(n * k) | Similar to string keys, avoids string join |
| Counter-based keys | O(n * k log k) | O(n * k) | Handles complex anagrams but slower |