← Index

Arrays & Hashing

Valid AnagramEasy

Given two strings s and t, return true if t is an anagram of s — same letters, same counts, any order.

Examples

Input: s = "anagram", t = "nagaram" → Output: true
Input: s = "rat", t = "car" → Output: false

Approach

Sorting both strings and comparing is the obvious first move — anagrams sort to the same string. It works, but pays an O(n log n) sorting cost you don't actually need. Counting characters gets there in O(n): build a frequency map of s, then walk t decrementing counts as you go. If any character in t is missing or already at zero, they're not anagrams.

Complexity — best & worst case

Sort approach — time O(n log n)
Optimal (counting) — time O(n) worst case, O(1) best case (lengths differ, instant false)
Optimal (counting) — space O(1) — at most 26 letters (or a fixed alphabet) in the map

Code

// Given two strings s and t, return true if t is an anagram of s
// (same letters, same counts, any order).

// --- Brute force: sort both strings and compare ---
function isAnagramSort(s, t) {
  if (s.length !== t.length) return false;
  const sortStr = (str) => str.split("").sort().join("");
  return sortStr(s) === sortStr(t);
}

// --- Optimal: count characters in one pass, no sorting needed ---
function isAnagram(s, t) {
  if (s.length !== t.length) return false;

  const counts = new Map();
  for (const char of s) {
    counts.set(char, (counts.get(char) || 0) + 1);
  }
  for (const char of t) {
    if (!counts.has(char) || counts.get(char) === 0) return false;
    counts.set(char, counts.get(char) - 1);
  }
  return true;
}

// --- Example Usage ---
console.log(isAnagram("anagram", "nagaram")); // true
console.log(isAnagram("rat", "car"));         // false
console.log(isAnagramSort("listen", "silent")); // true