Problem Statement
You are given an array of strings strs
. The task is to group the strings that are anagrams of each other.
Definition: Two strings are anagrams if they have the same characters in the same frequency but possibly in a different order.
Example:
Input: ["eat", "tea", "tan", "ate", "nat", "bat"] Output: [["eat","tea","ate"], ["tan","nat"], ["bat"]]
Constraints:
- All inputs are lowercase letters.
- Order of the output groups or the strings inside a group does not matter.
Approach
The main idea is to use a hash map to group strings by a unique key that identifies anagrams. There are two common ways to generate such a key:
Method 1: Sorting
- For each string, sort its characters alphabetically.
- Use the sorted string as a key in a hash map.
- All strings with the same sorted characters are anagrams and will map to the same key.
Example:
"eat"
→ sorted →"aet"
"tea"
→ sorted →"aet"
"tan"
→ sorted →"ant"
So the map will look like:
"aet" -> ["eat", "tea", "ate"] "ant" -> ["tan", "nat"] "abt" -> ["bat"]
Method 2: Character Count (Optimized)
- Count the frequency of each character in the string.
- Convert the count into a string key (e.g.,
"a1e1t1"
for"eat"
). - This avoids the sorting step and can be faster for longer strings.
Example:
"eat"
→ count →[1,0,0,...,1,...,1,...]
→"1,0,0,...,1,...,1,..."
"tea"
→ same count → same key
Java Implementation (Sorting Method)
import java.util.*; public class GroupAnagrams { public static List<List<String>> groupAnagrams(String[] strs) { if (strs == null || strs.length == 0) return new ArrayList<>(); Map<String, List<String>> map = new HashMap<>(); for (String s : strs) { char[] chars = s.toCharArray(); Arrays.sort(chars); // sort characters String key = new String(chars); // convert sorted char array to string // add string to the list for this key if (!map.containsKey(key)) { map.put(key, new ArrayList<>()); } map.get(key).add(s); } return new ArrayList<>(map.values()); } public static void main(String[] args) { String[] input = {"eat", "tea", "tan", "ate", "nat", "bat"}; List<List<String>> result = groupAnagrams(input); System.out.println(result); } }
Output:
[[eat, tea, ate], [tan, nat], [bat]]
Java Implementation (Character Count Method)
import java.util.*; public class GroupAnagramsOptimized { public static List<List<String>> groupAnagrams(String[] strs) { if (strs == null || strs.length == 0) return new ArrayList<>(); Map<String, List<String>> map = new HashMap<>(); for (String s : strs) { int[] count = new int[26]; for (char c : s.toCharArray()) { count++; } // convert count array to string key StringBuilder sb = new StringBuilder(); for (int i = 0; i < 26; i++) { sb.append('#'); // delimiter to avoid ambiguity sb.append(count[i]); } String key = sb.toString(); map.computeIfAbsent(key, k -> new ArrayList<>()).add(s); } return new ArrayList<>(map.values()); } public static void main(String[] args) { String[] input = {"eat", "tea", "tan", "ate", "nat", "bat"}; List<List<String>> result = groupAnagrams(input); System.out.println(result); } }
Advantages:
- Sorting method: simple and easy to understand.
- Count method: faster for long strings (O(NK)) instead of O(NK*logK) for sorting, where
K
is string length.
Key Points:
- HashMap is the core data structure for grouping anagrams.
- Sorting strings or counting characters generates a unique key for each anagram group.
- Use
List<List<String>>
to return the grouped anagrams. computeIfAbsent
is a convenient Java 8+ method to initialize lists in a map.