2Brute2Best
🔥0

Valid Anagram

Easy·LeetCode #242Basic Anchor
LeetCode
30-Second Mental ModelArrays & Hashing — Grouping by a canonical key (count signature)
Complexity:O(N²)→O(N)
Key Insight

Two strings are anagrams exactly when every letter appears the same number of times in both. Keep one array count[26]. Each letter of s adds 1, each letter of t subtracts 1. If every count ends at 0, the letters balance out perfectly.

Core Validity Invariant

t is an anagram of s exactly when the lengths are equal and count[c] == 0 for all 26 letters after reading both strings.

01

Problem

You are given two strings s and t.

Return true if t is an anagram of s, and false otherwise.

An anagram uses exactly the same letters, each one the same number of times, just possibly in a different order. For example, "listen" and "silent" are anagrams.

Input

Two strings s and t of lowercase English letters.

Output

true if t is a rearrangement of s, otherwise false.

Example 1
Input: s = "anagram", t = "nagaram"
Output: true

Both strings have three 'a', one 'n', one 'g', one 'r' and one 'm'. Only the order is different.

Example 2
Input: s = "rat", t = "car"
Output: false

s has a 't' but t has a 'c' instead, so the letters do not match.

Constraints
  • • 1 ≤ s.length, t.length ≤ 5 · 10^4
  • • s and t contain only lowercase English letters
  • • Follow-up: what if the strings can contain any Unicode characters?
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    If two strings have different lengths, can they ever be anagrams?

  2. 2.

    Does the order of the letters matter for the answer at all?

  3. 3.

    What single piece of information about a word stays the same no matter how I shuffle its letters?

  4. 4.

    Is it enough to know which letters appear, or do I also need how many times?

  5. 5.

    There are only 26 possible letters. How could that help?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFor each letter of s, find an unused copy in t and cross it outO(N²)O(N)
BetterSort both strings; anagrams become the same stringO(N log N)O(N)
Optimalcount[c]++ for s, count[c]-- for t, all must end at 0O(N)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “anagram / rearrangement”Order doesn't matter → describe each string by something order-free (sorted form or letter counts).
  • “same letters, same number of times”Counts matter, not just which letters appear → a set is not enough, use a count array.
  • “only lowercase letters”26 possible keys → a fixed array beats a hash map.
Order doesn't matter+counts must match+small fixed alphabet→Arrays & Hashing — Grouping by a canonical key (count signature)

This is the anchor of the sub-pattern. The core move is to replace a messy object (a word in some order) with a canonical key that is the same for everything that should count as equal: the sorted word, or its 26 letter counts. Here we only compare two keys. In Group Anagrams we will use the same key to group many words, and in Valid Sudoku the key becomes "which row / column / box".

10

Don't make this mistake

Forgetting the length check
✗ for (char c : s) count[c - 'a']++; for (char c : t) count[c - 'a']--; // ... but in the brute force: only search for s's letters in t
✓ if (s.size() != t.size()) return false;

In the brute force, "ab" vs "abc" finds a partner for every letter of s and returns true — the extra 'c' is never checked. In the optimal code the length check also lets you read s[i] and t[i] with one index without going out of bounds.

Using a set instead of counts (pattern confusion)
✗ set<char> a(s.begin(), s.end()), b(t.begin(), t.end()); return a == b;
✓ int count[26] = {0}; // ++ for s, -- for t, all must be 0

A set only remembers which letters appear, not how many times. "aab" and "abb" both give the set {a, b} and have the same length, but they are not anagrams. The key must keep the counts.

Checking only one direction of the counts
✗ for (char c : t) if (--count[c - 'a'] < 0) return false; return true; // without the length check
✓ Check the lengths first, or check that every count is exactly 0 at the end.

Stopping on a negative count only catches letters t has too many of. Without equal lengths, s could still have leftover letters (positive counts).

Using a fixed array for Unicode input
✗ int count[26]; count[c - 'a']++; // c could be 'é' or an emoji
✓ unordered_map<char32_t, int> count; // same ++ / -- idea

c - 'a' is out of range for anything that is not a lowercase letter. For the follow-up, switch to a hash map keyed by the character (decode UTF-8 to code points first). The idea stays the same.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Arrays & Hashing translate into production architectures and low-level memory mechanics.