Problem Statement
Given an array of strings strs, group the anagrams together. You can return the answer in any order.
An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
Example 1:
Input: strs = [“eat”,“tea”,“tan”,“ate”,“nat”,“bat”]
Output: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
Example 2:
Input: strs = [""]
Output: [[""]]
Example 3:
Input: strs = [“a”]
Output: [[“a”]]
Constraints:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i] consists of lowercase English letters.
Solution:
Here we have input as a slice of string, and we need to group the strings that are anagrams.
Following is the logic of the below solution:
- for each string s
- find the frequency of each character in
s
- create a key in a hash map using the frequency
- append the string in the slice of string associated with the frequency key.
- find the frequency of each character in
- for each key generate the expected response as slice of slice of string.
Here the important part is that for given 2 strings if they are anagrams then the frequency of the characters in them will match.
For example: If s1 = “eat”, s2 = “ate” are 2 strings then,
the frequency of characters in s1 is
e - 1, a - 1, t - 1
the frequency of characters in s1 is
a - 1, t - 1, e - 1
Thus the key generated for both of them will be
1#1#1#
and both the strings will be part of the same group,
so the map will represent it as
{
"1#1#1#": ["eat", "ate"] // order doesn't matter
}
Code:
func groupAnagrams(strs []string) [][]string {
m := make(map[string][]string)
for i := range strs {
key := getKey(strs[i]) // get frequency key
m[key] = append(m[key], strs[i])
}
// generate response
var res [][]string
for k := range m {
res = append(res, m[k])
}
return res
}
// getKey will take a string and will return a string which will
// have the frequency of each character in a-z order separated by a `#`
func getKey(s string) string {
// since the constraint is only small case english alphabets
counts := [26]int{}
for i := range s {
idx := s[i] - 'a'
counts[idx] += 1
}
var key string
for i := range counts {
key += fmt.Sprint(counts[i]) + "#"
// adding a break point of `#` because frequency can be more than 1 digit,
// helping us to identify whether its a new frequency count or not.
}
return key
}
Interestingly this frequency counting has a whole different level of applications, you can check Frequency Analysis for more details.
To see how to know whether 2 strings are anagrams of each other checkout Valid Anagrams
Thank you for reading through, let me know if you have any feedback. You can always reach out to me on @rajkumarGosavi .