Group Strings That Are Anagrams of Each Other
Solve this Problemstrs, group the anagrams together. Two strings are anagrams of each other if one can be rearranged into the other using every letter exactly once. You can return the groups — and the strings inside each group — in any order.
Comparing every pair of strings directly is expensive. The key insight: two strings are anagrams exactly when their letters, sorted, produce the same string — so sorting each string's letters gives a canonical "key" that's identical for every member of a group. Scanning a list of seen keys works but is quadratic; storing groups in a hash map keyed by that sorted string collapses lookups to O(1), leaving sorting as the only real cost.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ strs.length ≤ 10⁴ - ◆
0 ≤ strs[i].length ≤ 100 - ◆
strs[i] consists of lowercase English letters
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public String[][] groupAnagrams(String[] strs) { |
| 3 | Map<String, List<String>> map = new HashMap<>(); |
| 4 | for (String str : strs) { |
| 5 | char[] arr = str.toCharArray(); |
| 6 | Arrays.sort(arr); |
| 7 | String key = new String(arr); |
| 8 | map.putIfAbsent(key, new ArrayList<>()); |
| 9 | map.get(key).add(str); |
| 10 | } |
| 11 | String[][] result = new String[map.size()][]; |
| 12 | int i = 0; |
| 13 | for (List<String> group : map.values()) { |
| 14 | result[i++] = group.toArray(new String[0]); |
| 15 | } |
| 16 | return result; |
| 17 | } |
| 18 | } |
| 19 |
eataetstrs[0] = "eat" — sort its letters to get key "aet".
Approach & Solutions
Brute Force — Sort Each String, Linear Search for Its Group
BruteSort the letters of each string to get a canonical "key" — two strings are anagrams exactly when their sorted forms are identical. Keep a running list of keys seen so far; for every new string, scan that list from the start looking for a match. Found it → join that group. Not found → start a new group. The linear scan over already-seen keys is what makes this quadratic overall.
O(n² · k log k)O(n · k)1class Solution {
2 public String[][] groupAnagrams(String[] strs) {
3 List<String> keys = new ArrayList<>();
4 List<List<String>> groups = new ArrayList<>();
5 for (String str : strs) {
6 char[] arr = str.toCharArray();
7 Arrays.sort(arr);
8 String key = new String(arr);
9 int index = keys.indexOf(key);
10 if (index == -1) {
11 keys.add(key);
12 List<String> newGroup = new ArrayList<>();
13 newGroup.add(str);
14 groups.add(newGroup);
15 } else {
16 groups.get(index).add(str);
17 }
18 }
19 String[][] result = new String[groups.size()][];
20 for (int i = 0; i < groups.size(); i++) {
21 result[i] = groups.get(i).toArray(new String[0]);
22 }
23 return result;
24 }
25}Optimal — Group by Sorted-Character Key (Hash Map)
OptimalSame canonical key idea, but instead of scanning a list of keys, store groups in a hash map keyed by that sorted string. Looking up or creating a group is now O(1) — no scanning required — so the total time collapses to just the cost of sorting each string's letters.
O(n · k log k)O(n · k)1class Solution {
2 public String[][] groupAnagrams(String[] strs) {
3 Map<String, List<String>> map = new HashMap<>();
4 for (String str : strs) {
5 char[] arr = str.toCharArray();
6 Arrays.sort(arr);
7 String key = new String(arr);
8 map.putIfAbsent(key, new ArrayList<>());
9 map.get(key).add(str);
10 }
11 String[][] result = new String[map.size()][];
12 int i = 0;
13 for (List<String> group : map.values()) {
14 result[i++] = group.toArray(new String[0]);
15 }
16 return result;
17 }
18}