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
Kis 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. computeIfAbsentis a convenient Java 8+ method to initialize lists in a map.
