Group Anagrams
Group strings that are anagrams of each other — hash map keyed by sorted form.
2 min read
hash-map sorting strings
Problem#
Given an array of strings, group those that are anagrams of each other into the same sub-list.
Examples#
["eat","tea","tan","ate","nat","bat"]→[["bat"],["nat","tan"],["ate","eat","tea"]].
Constraints#
1 <= strs.length <= 10^4,0 <= strs[i].length <= 100.
Hints#
Hint
All anagrams share the same sorted character sequence — group on that.
Approach#
For each string, compute its sorted copy (canonical anagram form) and bucket the original by that key. Output the buckets.
Solution#
class Solution {public: vector<vector<string>> groupAnagrams(vector<string>& strs) { unordered_map<string, vector<string>> groups; for (auto& s : strs) { string k = s; sort(k.begin(), k.end()); groups[k].push_back(s); } vector<vector<string>> ans; ans.reserve(groups.size()); for (auto& [_, v] : groups) ans.push_back(std::move(v)); return ans; }};import "sort"
func groupAnagrams(strs []string) [][]string { groups := map[string][]string{} for _, s := range strs { b := []byte(s) sort.Slice(b, func(i, j int) bool { return b[i] < b[j] }) k := string(b) groups[k] = append(groups[k], s) } ans := make([][]string, 0, len(groups)) for _, v := range groups { ans = append(ans, v) } return ans}from collections import defaultdictfrom typing import List
class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: groups: dict = defaultdict(list) for s in strs: key = ''.join(sorted(s)) groups[key].append(s) return list(groups.values())function groupAnagrams(strs) { const groups = new Map(); for (const s of strs) { const key = s.split('').sort().join(''); if (!groups.has(key)) groups.set(key, []); groups.get(key).push(s); } return Array.from(groups.values());}class Solution { public List<List<String>> groupAnagrams(String[] strs) { Map<String, List<String>> groups = new HashMap<>(); for (String s : strs) { char[] arr = s.toCharArray(); Arrays.sort(arr); String key = new String(arr); groups.computeIfAbsent(key, k -> new ArrayList<>()).add(s); } return new ArrayList<>(groups.values()); }}function groupAnagrams(strs: string[]): string[][] { const groups = new Map<string, string[]>(); for (const s of strs) { const key = s.split('').sort().join(''); if (!groups.has(key)) groups.set(key, []); groups.get(key)!.push(s); } return Array.from(groups.values());}Editorial#
Sorting each string gives an O(L log L) canonical form — clean and concise. For tighter constants, replace the sorted key with the count signature "a3b1c2..." for O(L) keying. Both correctly cluster anagrams.
Complexity#
- Time: O(N * L log L).
- Space: O(N * L).
Concept revision#
Related#