5 Best Ways to Check Whether Two Strings Are Anagrams of Each Other in Python

πŸ’‘ Problem Formulation: Determining if two strings are anagrams is a classic problem that involves verifying whether the strings contain the same characters in a different order. For instance, “listen” and “silent” are anagrams, as rearranging the letters of “silent” can produce “listen”. The desired output is a boolean value; True if the strings are anagrams, and False otherwise.

Method 1: Sorting and Comparison

This method involves sorting both strings and comparing the sorted versions for equality. If the sorted strings are equal, they are anagrams. The Python function sorted() returns a list of sorted characters, which can be joined back into a string for comparison.

Here’s an example:

def are_anagrams(str1, str2):
    return sorted(str1) == sorted(str2)

print(are_anagrams("listen", "silent"))

Output: True

By sorting the strings, this code snippet rearranges the characters in a defined order. Comparing the sorted results directly tells us if the original strings were made of the same characters, making it an efficient and easy-to-understand approach.

Method 2: Using a Dictionary

This method counts the frequency of each character in the strings using a dictionary. If both dictionaries match, the strings are anagrams of each other. Python dictionaries are optimal for this task due to their key-value nature, allowing character counting.

Here’s an example:

from collections import Counter

def are_anagrams(str1, str2):
    return Counter(str1) == Counter(str2)

print(are_anagrams("triangle", "integral"))

Output: True

The Counter class from the collections module provides a straightforward way to count the occurrences of each character. Comparing two Counter objects tells us if both strings have identical character counts.

Method 3: Increment and Decrement Counts

A slight variation and optimization from using a dictionary is to use a list of 26 elements representing each alphabet letter. The idea is to increment the count for each character in the first string and decrement for each character in the second string. If the list is all zeros at the end, the strings are anagrams.

Here’s an example:

def are_anagrams(str1, str2):
    if len(str1) != len(str2):
        return False
    counts = [0] * 26
    for char in str1:
        counts[ord(char) - ord('a')] += 1
    for char in str2:
        counts[ord(char) - ord('a')] -= 1
    return all(count == 0 for count in counts)

print(are_anagrams("binary", "brainy"))

Output: True

This approach is efficient as it only requires a single scan of each string and operates in linear time, making it suitable for large strings. However, it assumes the strings contain only lowercase English letters.

Method 4: Prime Multiplication

Another method is to assign each letter a unique prime number and multiply these numbers for each string. Due to the fundamental theorem of arithmetic, if the products are the same, the strings are anagrams. This is an interesting mathematical approach to the problem.

Here’s an example:

def are_anagrams(str1, str2):
    if len(str1) != len(str2):
        return False
    primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101]
    product = lambda s: reduce(lambda x, y: x * primes[ord(y) - ord('a')], s, 1)
    return product(str1) == product(str2)

from functools import reduce
print(are_anagrams("stop", "pots"))

Output: True

While unique in approach, this method might suffer from integer overflow with very long strings as the product of prime numbers can grow very large. It’s also limited to the English alphabet and case-sensitive inputs.

Bonus One-Liner Method 5: Using Python’s Set

This one-liner uses a set to eliminate duplicate characters and checks for equality of sorted sets. It’s a quick approach, suitable for determining if strings have equal unique characters but does not account for character frequency.

Here’s an example:

are_anagrams = lambda str1, str2: set(str1) == set(str2)

print(are_anagrams("sadder", "dreads"))

Output: True

As a one-liner, it’s a clever trick but not foolproof since it ignores character counts. It will incorrectly identify “sadder” and “dreads” as anagrams despite the differing number of ‘d’s and ‘s’s.

Summary/Discussion

  • Method 1: Sorting and Comparison. Easy to understand. Suitable for small to medium-sized strings. Time complexity is O(n log n).
  • Method 2: Using a Dictionary. Handles character frequency well. Works for any Unicode characters. Linear time complexity but requires extra space for the dictionary.
  • Method 3: Increment and Decrement Counts. Optimized for English alphabet. It’s efficient and works in linear time but doesn’t handle uppercases or other character sets.
  • Method 4: Prime Multiplication. Unique and mathematically intriguing. Limited to English alphabet and can have integer overflow issues.
  • Bonus One-Liner Method 5: Using Python’s Set. Quick for unique character comparison but does not consider character frequency, which is critical to anagrams.