49. Group Anagrams
Leetcode Hash Table StringGiven an array of strings, group anagrams together.
Example:
Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
Note:
- All inputs will be in lowercase.
- The order of your output does not matter.
分析¶
一开始想到了最笨的方法,对于每个字符串,与其他字符串一一比对,如果是错位词,则加入到相应的List中。判断错位词详见LeetCode 242. Valid Anagram。可惜这种方法超时了。
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
boolean isFind;
for (int i = 0; i < strs.length; i++) {
isFind = false;
for (String str: map.keySet()) {
if (isAnagram(str, strs[i])) {
res.get(map.get(str)).add(strs[i]);
isFind = true;
continue;
}
}
if (!isFind) {
res.add(new ArrayList<String>());
res.get(res.size() - 1).add(strs[i]);
map.put(strs[i], res.size() - 1);
}
}
return res;
}
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
// 一共只有26个字母
int[] count = new int[26];
for (int i = 0; i < s.length(); i++) {
count[s.charAt(i) - 'a']++;
count[t.charAt(i) - 'a']--;
}
for (int num : count)
if (num != 0) return false;
return true;
}
上面的方法之所以慢,是因为需要一一比对。如果n非常大时,而且分组非常大时,时间复杂度接近于O(n^2)。所以用哈希表来判断错位词比较合适。因为判断错位词的方法一般有2种(LeetCode 242. Valid Anagram):排序和分类计数。所以这里也可以应用这两种方法。
首先是排序的方法:
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List> map = new HashMap<>();
for (String str : strs) {
char[] c = str.toCharArray();
Arrays.sort(c);
String s = String.valueOf(c);
if (map.containsKey(s)) map.get(s).add(str);
else map.put(String.valueOf(s), new ArrayList<>(Collections.singletonList(str)));
}
return new ArrayList(map.values());
}
然后是分类计数的方法:
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List> map = new HashMap<>();
for (String str : strs) {
int[] nums = new int[26];
for (char c : str.toCharArray())
nums[c - 'a']++;
StringBuilder sb = new StringBuilder();
for (int num : nums)
sb.append(num);
String s = sb.toString();
if (map.containsKey(s)) map.get(s).add(str);
else map.put(String.valueOf(s), new ArrayList<>(Collections.singletonList(str)));
}
return new ArrayList(map.values());
}