Anagram Check Techniques in DSA Javascript - Time & Space Complexity
Checking if two words are anagrams means seeing if they have the same letters in any order.
We want to know how the time needed changes as the words get longer.
Analyze the time complexity of the following code snippet.
function areAnagrams(str1, str2) {
if (str1.length !== str2.length) return false;
const count = {};
for (const char of str1) {
count[char] = (count[char] || 0) + 1;
}
for (const char of str2) {
if (!count[char]) return false;
count[char]--;
}
return true;
}
This code checks if two strings are anagrams by counting letters in the first and matching with the second.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two loops each going through all characters of the strings.
- How many times: Each loop runs once for every character, so twice total but separate.
As the strings get longer, the number of steps grows roughly in direct proportion to their length.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 steps (two loops of 10 each) |
| 100 | About 200 steps |
| 1000 | About 2000 steps |
Pattern observation: Doubling the input roughly doubles the work done.
Time Complexity: O(n)
This means the time needed grows in a straight line with the length of the strings.
[X] Wrong: "Sorting the strings is always faster for checking anagrams."
[OK] Correct: Sorting takes more time (O(n log n)) than counting letters (O(n)), so counting is usually faster.
Understanding how to check anagrams efficiently shows you can choose the right approach for different problems.
"What if we used sorting instead of counting? How would the time complexity change?"
Practice
Solution
Step 1: Understand the definition of anagrams
Anagrams are words or phrases made by rearranging the letters of another, so they must have the same characters.Step 2: Compare the character sets
If two strings have exactly the same characters, just in different orders, they are anagrams.Final Answer:
They contain the same characters in any order -> Option CQuick Check:
Anagrams = same characters [OK]
- Thinking same length means anagrams
- Assuming same first letter means anagrams
- Ignoring character counts
Solution
Step 1: Understand string and array methods
Strings need to be split into arrays to sort, then joined back to strings for comparison.Step 2: Check each option's correctness
const areAnagrams = (a, b) => a.split('').sort().join('') === b.split('').sort().join(''); correctly splits, sorts, and joins both strings before comparing. const areAnagrams = (a, b) => a.split('').sort() === b.split('').sort(); compares arrays directly (wrong). const areAnagrams = (a, b) => a.sort() === b.sort(); tries to sort strings directly (invalid). const areAnagrams = (a, b) => a.split().sort().join() === b.split().sort().join(); uses split() without argument and join() without argument, which is incorrect.Final Answer:
const areAnagrams = (a, b) => a.split('').sort().join('') === b.split('').sort().join(''); -> Option DQuick Check:
Split + sort + join = correct syntax [OK]
- Comparing arrays directly with ===
- Not joining arrays back to strings
- Using split() without arguments
function isAnagram(s1, s2) {
if (s1.length !== s2.length) return false;
const count = {};
for (const char of s1) {
count[char] = (count[char] || 0) + 1;
}
for (const char of s2) {
if (!count[char]) return false;
count[char]--;
}
return true;
}
console.log(isAnagram('listen', 'silent'));
console.log(isAnagram('hello', 'bello'));Solution
Step 1: Analyze the first call isAnagram('listen', 'silent')
Both strings have same length. Counting characters in 'listen' and subtracting counts for 'silent' matches perfectly, so returns true.Step 2: Analyze the second call isAnagram('hello', 'bello')
Strings have same length but 'hello' has 'h' which 'bello' does not. The count check fails and returns false.Final Answer:
true false -> Option AQuick Check:
Matching counts = true, mismatch = false [OK]
- Ignoring length check
- Not decrementing counts properly
- Returning true too early
function checkAnagram(a, b) {
const map = new Map();
for (let i = 0; i < a.length; i++) {
map.set(a[i], (map.get(a[i]) || 0) + 1);
map.set(b[i], (map.get(b[i]) || 0) - 1);
}
for (const val of map.values()) {
if (val !== 0) return false;
}
return true;
}Solution
Step 1: Identify missing length check
The code lacks an initial check to ensure both strings have the same length.Step 2: Understand the impact of missing length check
If `a.length < b.length`, the loop only iterates `a.length` times, incrementing counts for all of `a` but decrementing only the first `a.length` characters of `b`. Extra characters in `b` are ignored, potentially returning `true` incorrectly. Example: `checkAnagram('ab', 'abc')` balances 'a' and 'b' but ignores 'c', wrongly returns `true`. If `a` longer, it may detect mismatch via extra increments or `undefined` key.Final Answer:
It does not check string lengths before processing -> Option BQuick Check:
Missing length check = false positives [OK]
- Updating counts for both strings simultaneously
- Assuming Map is invalid in JS
- Missing length check
function isAnagramAdvanced(s1, s2) {
// Fill in the blanks
}Solution
Step 1: Normalize both strings
Remove all spaces and convert both strings to lowercase to ignore case and spaces.Step 2: Sort and compare normalized strings
Sort the characters of both normalized strings and compare them to check if they are anagrams.Final Answer:
Normalize strings by removing spaces and lowercasing, then compare sorted characters -> Option AQuick Check:
Normalize + sort + compare = correct approach [OK]
- Ignoring spaces in one string only
- Comparing lengths without normalization
- Using includes() which is incorrect for anagrams
Ready to prove it?
Pass the test and this pattern moves unknown
