Valid Anagram

You are given two strings s and t made of lowercase English letters.

Return true if t is an anagram of s, and false otherwise. Two strings are anagrams when one can be turned into the other by reordering its letters, using every letter exactly as many times as it appears. In other words, every letter must occur the same number of times in both strings.

Example 1

Input: s = "night", t = "thing" Output: true Why: Both words use the letters g, h, i, n and t once each.

Example 2

Input: s = "hello", t = "bello" Output: false Why: The first word has an h where the second has a b.

Example 3

Input: s = "a", t = "ab" Output: false Why: The strings have different lengths, so they cannot use exactly the same letters.

Constraints

  • 1 <= s.length, t.length <= 5 * 104
  • s and t consist of lowercase English letters.

Pattern Path · Hashing & Counting · problem 2 of 169

Order does not matter here, only how often each letter appears. What summary of a string captures that?
Two strings are anagrams exactly when their letter counts are identical.
Count the letters of s, then walk through t and subtract. If any count would go below zero (or the lengths differ), the answer is false.
Target: O(n) time, O(1) extra space.

Start simple

Sort both strings and compare them: O(n log n) time; trying every rearrangement would be factorial.

The key idea

An anagram ignores order completely, so the only thing that matters about each string is its multiset of letters: how many a's, how many b's, and so on. Two strings are anagrams exactly when those counts match.

First compare lengths: if they differ, the answer is immediately false. Otherwise count the letters of s in a table, then walk through t and decrement the count of each letter. If a count would drop below zero, t uses that letter more often than s does, so return false.

If the walk finishes, every count is exactly zero: the lengths are equal and no count went negative, so none can be left positive either. With only 26 possible letters the table is a fixed size, which makes the extra space O(1); a hash map works the same way for larger alphabets.

Complexity

  • Time: O(n)
  • Space: O(1)

Python

from collections import Counter


class Solution:
    def isAnagram(self, s, t):
        if len(s) != len(t):
            return False
        counts = Counter(s)
        for ch in t:
            counts[ch] -= 1
            if counts[ch] < 0:  # t uses this letter more often than s does
                return False
        return True

JavaScript

var isAnagram = function(s, t) {
  if (s.length !== t.length) return false;
  const counts = new Array(26).fill(0);
  const A = 'a'.charCodeAt(0);
  for (let i = 0; i < s.length; i++) counts[s.charCodeAt(i) - A]++;
  for (let i = 0; i < t.length; i++) {
    const k = t.charCodeAt(i) - A;
    counts[k]--;
    if (counts[k] < 0) return false; // t uses this letter more often than s does
  }
  return true;
};

What the interviewer is checking

The interviewer is looking for the counting idea (and the sort-based alternative), plus a discussion of how the answer changes for Unicode or very large alphabets.

Mistakes to avoid

  • Comparing only the sets of letters: "aab" and "abb" use the same letters but different counts.
  • Forgetting the length check when you only verify that counts never go negative.
  • Using a fixed 26-slot array when the input might contain characters outside a to z.

Follow-ups to expect

  • What if the strings contain arbitrary Unicode characters? (Use a hash map, not 26 slots.)
  • How would you group a list of words into anagram families? (Key each word by sorted letters or counts.)
  • How would you find all anagrams of p inside a longer string? (Sliding window of counts.)

In real software

Comparing frequency signatures instead of exact sequences shows up in spell checkers, word games, and checking that two batches contain the same items regardless of order.

Practice next

Next Post Previous Post
No Comment
Add Comment
comment url