原题:

排序作为 key
两个字母异位词的组成完全相同 -> 排序后完全相同
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String s : strs) {
char[] chars = s.toCharArray();
// 对字符数组排序:异位词排序后字符序列必然相同
Arrays.sort(chars);
// 转回字符串,作为哈希表的 key
String key = new String(chars);
// 如果 key 不存在,就新建一个空 ArrayList;然后取出该分组列表
// 把当前原始字符串 s 加入对应分组
// if (!map.containsKey(key)) map.put(key, new ArrayList<>());
// map.get(key).add(s);
map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
}
//包装成 ArrayList 返回
return new ArrayList<>(map.values());
}
}
时间:O (n・k log k)
空间:O (n・k)
更优雅一点的解法
异位词的特征是「每个字母出现的次数相同」。
所以用一个长度为 26 的计数数组描述它:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] count = new char[26];
for (int i = 0; i < str.length(); i++) {
count[str.charAt(i) - 'a']++;
}
String key = new String(count);
//if (!map.containsKey(key)) {
//map.put(key, new ArrayList<>());
//}
//map.get(key).add(str);
// key 第一次出现,新建空列表放进去
// 取出该分组列表,加入当前字符串
map.computeIfAbsent(key, k -> new ArrayList<>()).add(str);
}
return new ArrayList<>(map.values());
}
}
时间:O(n · k)
空间:O(n · k)
拓展
数据小可以用质数法
把每一个字符对应一个质数 质数乘积当成 key
不同字母组合的乘积必然不同,异位词的乘积必然相同。
这题用这个会爆
但是可以改成大数来存
import java.math.BigInteger;
class Solution {
private static final int[] PRIMES = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101
};
public List<List<String>> groupAnagrams(String[] strs) {
Map<BigInteger, List<String>> map = new HashMap<>();
for (String s : strs) {
BigInteger key = BigInteger.ONE;
for (int i = 0; i < s.length(); i++) {
int index = s.charAt(i) - 'a';
key = key.multiply(BigInteger.valueOf(PRIMES[index]));
}
map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
}
return new ArrayList<>(map.values());
}
}
这里觉得没有必要 还慢 内存也大