Reference: LeetCode
Difficulty: Medium
Problem
Given an array of strings, group anagrams together.
Note:
- All inputs will be in lowercase.
- The order of your output does not matter.
Example:
1 2 3 4 5 6 7
| Input: ["eat", "tea", "tan", "ate", "nat", "bat"], Output: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ]
|
Analysis
HashMap + Sorting
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public 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) { String key = sortString(s); List<String> list = map.getOrDefault(key, new ArrayList<>()); list.add(s); map.put(key, list); } return new ArrayList<>(map.values()); }
private String sortString(String str) { char[] arr = str.toCharArray(); Arrays.sort(arr); return String.valueOf(arr); }
|
Time: $O(NK\log{K})$ where $K$ is the maximum length of a string.
Space: $O(NK)$
Categorize by Count
Count a string’s characters and generate a key like #1#2#3#4...
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public List<List<String>> groupAnagrams(String[] strs) { if (strs.length == 0) return new ArrayList(); Map<String, List> ans = new HashMap<String, List>(); int[] count = new int[26]; for (String s : strs) { Arrays.fill(count, 0); for (char c : s.toCharArray()) count[c - 'a']++;
StringBuilder sb = new StringBuilder(""); for (int i = 0; i < 26; i++) { sb.append('#'); sb.append(count[i]); } String key = sb.toString(); if (!ans.containsKey(key)) ans.put(key, new ArrayList()); ans.get(key).add(s); } return new ArrayList(ans.values()); }
|
Time: $O(NK)$
Space: $O(NK)$