Problem Overview#
- We are given an array of strings
strs - Our goal is to group the anagrams together and return an array of array of strings
- All strings are in lowercase English letters
Leetcode - Group Anagrams
Example#
Input: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
nat and tan are anagramsate, eat and tea are anagrams- There is no anagram for
bat in the array
If you dont know how to find anagrams then refer this Valid Anagrams
Brute Force#
Intuition#
- We need to pick one string and using it, iterate over the other strings
- We need to check whether the character frequencies of the other string match the selected string
Code#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
int n = strs.size();
vector<vector<string>> result;
vector<int> isGrouped(n, 0);
for (int i = 0; i < n; i++) {
if (isGrouped[i] == 1)
continue;
vector<int> freq(26, 0);
string temp = strs[i];
for (auto it : temp) {
freq[it - 'a']++;
}
vector<string> group;
for (int j = i; j < n; j++) {
if (temp.size() != strs[j].size()) continue;
bool flag = isAnagram(strs[j], freq);
if (flag == true) {
group.push_back(strs[j]);
isGrouped[j] = 1;
}
}
result.push_back(group);
}
return result;
}
bool isAnagram(string str, vector<int> freq) {
for (char c : str) {
if (--freq[c - 'a'] < 0) {
return false;
}
}
return true;
}
};
|
Time and Space Complexity#
- Time — O(n² · m) — for each of the
n strings, we compare against n others, and each comparison scans up to m characters - Space — O(n) — for the
isGrouped array
Why It Fails#
- For every string, we’re comparing it against all other strings character by character
- This takes O(n² · m) time — too slow for large inputs
- We’re repeatedly scanning strings instead of using a smarter key to group them
Optimization#
Intuition#
- If two strings are anagrams, sorting them gives the same string — we can use that sorted string as a key to group them
Code#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> mp;
for (auto it : strs) {
string key = it;
sort(key.begin(), key.end());
mp[key].push_back(it);
}
vector<vector<string>> result;
for (auto& [key, group] : mp) {
result.push_back(group);
}
return result;
}
};
|
Time and Space Complexity#
- Time — O(n · m log m) — we iterate over all
n strings, and sorting each string of length m takes m log m - Space — O(n · m) — for storing all strings in the hashmap
Key Takeaways#
- Sometimes a small observation can lead you straight to the solution — like the fact that sorted anagrams are always identical strings