Valid Anagram
Given two strings s and t, determine if t is an anagram of s. An anagram is a word formed by rearranging the letters of another word using all original letters exactly once (e.g., “listen” and “silent”).
The most efficient approach uses frequency counting with a hash map, similar to techniques employed in Two Sum and Longest Substring Without Repeating Characters.
Hash Map Solution
#include <string>
#include <unordered_map>
using namespace std;
class Solution {
public:
bool isAnagram(string s, string t) {
// string can't be an anagram if it is of a different size
if (s.size() != t.size())
return false;
unordered_map<char, unsigned int> hashMap;
unordered_map<char, unsigned int> hashMap2;
for (int i = 0; i < s.size(); ++i) {
hashMap[s[i]] += 1;
hashMap2[t[i]] += 1;
}
return hashMap == hashMap2;
}
};Optimized Single-Pass Solution
Rather than using two hash maps, we can optimize with a single frequency array:
- Increment counts for characters in
s - Decrement counts for characters in
t - If all counts are zero at the end,
tis an anagram ofs
For lowercase English letters, a fixed-size array of 26 elements is more space-efficient than a hash map and provides access.
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
bool isAnagram(string s, string t) {
// string can't be an anagram if it is of a different size
if (s.size() != t.size())
return false;
vector<int> hashMap(26, 0);
for (int i = 0; i < s.size(); ++i) {
hashMap[s[i] - 'a'] += 1;
hashMap[t[i] - 'a'] -= 1;
}
for (int i = 0; i < 26; i++) {
if (hashMap[i] != 0)
return false;
}
return true;
}
};The above solution can be further optimised for memory by using an int array instead of a vector, as the size is fixed and known at compile time.
int hashMap[26] = {0}; // Initialize an array of size 26 to zero