Problem Statement
Given two strings s and t, return true if t is an anagram of s, and false otherwise.
An anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
The term Valid Anagram refers to the condition where two strings are anagrams of each other.
Example 1:
Input: s = "anagram", t = "nagaram"
Output: true
Explanation: Both strings contain the same characters with the same frequencies.Example 2:
Input: s = "rat", t = "car"
Output: false
Explanation: Different characters present.Constraints:
1 <= s.length, t.length <= 5 * 10^4sandtconsist of lowercase English letters
Follow-up:
What if the inputs contain Unicode characters? How would you adapt your solution?
Approach
Initial Thoughts
Two strings are anagrams if they contain exactly the same characters with the same frequencies. We need to verify that every character in s appears in t with identical count, and vice versa.
Strategy
Approach 1 (Sorting): Sort both strings and compare them. If they’re anagrams, sorted versions will be identical.
Approach 2 (Hash Map – Optimal): Count character frequencies in both strings using hash maps and compare the counts.
Approach 3 (Single Hash Map): Count frequencies in s, then decrement counts while iterating through t.
Key Insights
- Different lengths → automatically not anagrams (quick reject)
- Anagrams have identical character frequency distributions
- Sorting changes time complexity to O(n log n)
- Hash map approach achieves O(n) with O(1) space (only 26 lowercase letters)
- Can use array of size 26 instead of hash map for fixed alphabet
- Single pass with counting is more efficient than creating two separate counts
Algorithm Steps
Hash Map Approach:
- Quick check: If lengths differ, return
false - Create a hash map (or array of size 26) for character counts
- First pass: Iterate through
s, increment count for each character - Second pass: Iterate through
t, decrement count for each character - Validation: Check if all counts are zero
- If any count is non-zero, return
false - If all counts are zero, return
true
- If any count is non-zero, return
Sorting Approach (Alternative):
- If lengths differ, return
false - Sort both strings
- Compare sorted strings for equality
Complexity Analysis
Hash Map Approach:
Time Complexity: O(n) – Two passes through strings of length n (one for s, one for t)
Space Complexity: O(1) – Using array of size 26 for lowercase English letters (constant space). If using hash map, it’s still O(1) since at most 26 unique characters.
Sorting Approach:
Time Complexity: O(n log n) – Dominated by sorting operation
Space Complexity: O(1) or O(n) depending on sorting algorithm and language
Code
Solution 1: Two Hash Maps (Your Solution – Clean & Optimal)
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
# Quick reject if lengths differ
if len(s) != len(t):
return False
# Create separate hashmaps for both strings
s_hashmap = {}
t_hashmap = {}
# Build both hashmaps simultaneously in one pass
for i in range(len(s)):
s_hashmap[s[i]] = s_hashmap.get(s[i], 0) + 1
t_hashmap[t[i]] = t_hashmap.get(t[i], 0) + 1
# Compare the two hashmaps
return s_hashmap == t_hashmapSolution 2: Using Counter (Pythonic)
from collections import Counter
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
return Counter(s) == Counter(t)Solution 3: Sorting Approach
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
return sorted(s) == sorted(t)Solution 4: Single Hash Map (Space Optimized)
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
count = {}
# Increment for s, decrement for t
for i in range(len(s)):
count[s[i]] = count.get(s[i], 0) + 1
count[t[i]] = count.get(t[i], 0) - 1
# Check if all counts are zero
return all(val == 0 for val in count.values())Code Walkthrough
Two Hash Maps Solution (Your Solution):
Line 3-4: Quick optimization – if lengths differ, strings can’t be anagrams
- Saves time by avoiding unnecessary hashmap construction
Line 7-8: Initialize two empty hashmaps
s_hashmapwill store character frequencies for stringst_hashmapwill store character frequencies for stringt
Line 11: Single loop through both strings simultaneously
- More efficient than two separate loops
- Uses index
ito access characters from both strings at the same position
Line 12: Build frequency map for string s
s_hashmap.get(s[i], 0)returns current count or 0 if character not yet seen- Increment the count by 1
Line 13: Build frequency map for string t in the same iteration
- Same logic as line 12 but for string
t - This parallel construction is efficient and clean
Line 16: Compare the two hashmaps directly
- Python allows direct dictionary comparison with
== - Returns
Trueif both hashmaps have identical key-value pairs - Returns
Falseif any character has different frequency
Why this approach is excellent:
- Clean and readable code
- Single pass through strings (optimal)
- Direct hashmap comparison is elegant
- No need for complex validation logic
Alternative Approaches:
Single Hash Map (Solution 4):
- Uses one hashmap, incrementing for
sand decrementing fort - Slightly more space-efficient (one hashmap vs two)
- Needs extra validation at the end (
all(val == 0 for val in count.values()))
Counter (Solution 2):
- Most Pythonic and concise
- Essentially does the same thing as your solution under the hood
- Good for interviews to show Python knowledge
Edge Cases to Consider
- Different lengths:
s = "a",t = "ab"→false - Empty strings:
s = "",t = ""→true(both empty) - Single character – same:
s = "a",t = "a"→true - Single character – different:
s = "a",t = "b"→false - Same characters, different frequency:
s = "aa",t = "ab"→false - All same character:
s = "aaaa",t = "aaaa"→true - Long strings: Maximum length 50,000
- One character difference:
s = "abc",t = "abd"→false - Perfect anagrams:
s = "listen",t = "silent"→true
Similar Problems
- LC 242: Valid Anagram (this problem)
- LC 49: Group Anagrams
- LC 438: Find All Anagrams in a String
- LC 567: Permutation in String
- LC 383: Ransom Note
- LC 791: Custom Sort String
- LC 1347: Minimum Number of Steps to Make Two Strings Anagram
- LC 2273: Find Resultant Array After Removing Anagrams
Personal Notes
- This is a fundamental string problem that teaches character frequency counting
- Your solution (two hashmaps) is excellent because:
- Very clean and readable
- Single pass through both strings (optimal)
- Direct dictionary comparison is elegant and Pythonic
- Easy to understand and explain in interviews
- Three main approaches to know:
- Two hash maps: Clean, readable, O(n) time – your approach
- Single hash map with increment/decrement: Slightly more space-efficient
- Sorting: Simple but O(n log n)
- Interview tip: Your solution is perfect to present first
- Shows understanding of hashmaps
- Clean implementation
- Easy to explain
- Then mention Counter as a Pythonic alternative
- For the follow-up (Unicode): Your hashmap approach handles any characters automatically
- No changes needed for Unicode support
- Array approach only works for fixed, small alphabets
- Length check at the start is crucial optimization (fails fast)
- Why two hashmaps vs one:
- Two hashmaps: Simpler logic, direct comparison
- One hashmap: Saves a bit of space, but needs validation loop
- Both are O(n) time and O(1) space (at most 26 unique lowercase letters)
- Direct dictionary comparison with
==is a Python feature not all languages have - The
.get(key, default)pattern is cleaner than checkingif key in dict - Common mistake: Forgetting the length check at the beginning
- This pattern (character frequency) appears in many string problems
- Building both hashmaps in the same loop is more efficient than separate loops


