Skip to main content

How to Check if Two Strings are Anagrams in Python

Two strings are anagrams if they are made of the same characters with the same frequencies, arranged differently. Classic examples include "Listen" vs "Silent" or "Dormitory" vs "Dirty Room".

Checking for anagrams is a standard algorithmic problem often encountered in technical interviews. This guide covers the three most effective ways to solve it in Python.

1. The Standard Approach: collections.Counter

The most Pythonic and efficient solution is to count character frequencies. If two strings have identical character counts, they are anagrams.

Python’s collections.Counter handles this elegantly in $O(n)$ linear time.

from collections import Counter

def is_anagram(s1: str, s2: str) -> bool:
"""
Check if two strings are anagrams using character counts.
"""
# Counter objects compare equal if they hold the same data
return Counter(s1) == Counter(s2)

# Usage
print(is_anagram("listen", "silent")) # True
print(is_anagram("hello", "world")) # False

Why this is the best method

  • Performance: It iterates over the string once, resulting in $O(n)$ time complexity.
  • Readability: The code explicitly states the intent: "Are the counts of characters equal?"

2. The Robust Approach (Ignoring Case and Spaces)

In real-world applications (and advanced interview constraints), strings often contain mixed capitalization, spaces, or punctuation. "Dormitory" and "Dirty Room" are anagrams, but a strict comparison would fail due to the space and capital 'D'.

You must normalize the strings before comparing.

from collections import Counter

def is_anagram_robust(s1: str, s2: str) -> bool:
"""
Check for anagrams ignoring case and whitespace.
"""
# 1. Convert to lowercase
# 2. Remove spaces
clean_s1 = s1.lower().replace(" ", "")
clean_s2 = s2.lower().replace(" ", "")

return Counter(clean_s1) == Counter(clean_s2)

print(is_anagram_robust("Dormitory", "Dirty Room")) # True
Advanced Normalization

If you need to ignore punctuation as well (e.g., "Madam Curie" vs "Radium came."), use filter with str.isalnum:

clean_s1 = "".join(filter(str.isalnum, s1.lower()))

3. The "No Imports" Approach: Sorting

If you are restricted from using imported modules, or if you are writing a quick script where memory usage is not a concern, sorting is the easiest logic to implement. If you sort the characters of two anagrams, they become identical strings.

def is_anagram_sorted(s1: str, s2: str) -> bool:
"""
Check if two strings are anagrams by sorting them.
"""
return sorted(s1) == sorted(s2)

print(is_anagram_sorted("race", "care")) # True
note

Because sorting costs $O(n \log n)$, this method is theoretically slower than the Counter method for very large strings.

Complexity Comparison

MethodTime ComplexitySpace ComplexityRecommendation
Counter$O(n)$$O(1)$ *Best for Production. Fast, clean, and Pythonic.
sorted()$O(n \log n)$$O(n)$Good for constraints where imports aren't allowed.
Normalization$O(n)$$O(n)$Necessary for phrases or sentences.
note

Note on Space: The space complexity for Counter is technically $O(k)$ where $k$ is the number of unique characters. Since alphabet sizes are usually fixed constants (e.g., 26 letters), this is often considered $O(1)$ auxiliary space.

Summary

  • Use collections.Counter for the most efficient, O(n) solution.
  • Use sorted() if you need a quick one-liner without imports.
  • Always ask if case sensitivity and whitespace matter; if so, normalize your strings using .lower() and .replace().