这是一道经典的哈希表与字符串操作相关的题目,考察快速分组和使用数据结构的能力。所谓字母异位词,是指由相同的字母通过重新排列形成的不同单词。题目要求将一组字符串按照字母异位词分组。
给定一个字符串数组 strs
,将词组按照字母异位词进行分组,返回所有分组后的结果。字母异位词具有相同的字符,只是排列顺序不同。
输入输出示例:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]
输入: strs = [""]
输出: [[""]]
输入: strs = ["a"]
输出: [["a"]]
"eat"
和 "tea"
排序后都变成 "aet"
。import java.util.*;
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);
String key = new String(chars);
// 将排序后的字符串作为 key 插入哈希表
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(s);
}
// 返回哈希表中所有的值
return new ArrayList<>(map.values());
}
}
时间复杂度:
O(N)
,N
是字符串数组的长度。O(K log K)
,K
是每个字符串的平均长度。O(N * K log K)
。空间复杂度:
O(N * K)
。"eat"
和 "tea"
的字母分布均为 {e:1, a:1, t:1}
。O(K log K)
降低到 O(K)
。import java.util.*;
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// 使用一个哈希表存储分组结果
Map<String, List<String>> map = new HashMap<>();
// 遍历数组中的每个字符串
for (String s : strs) {
// 统计字符频率
int[] count = new int[26];
for (char c : s.toCharArray()) {
count[c - 'a']++;
}
// 将频率数组转化为字符串作为 key
StringBuilder keyBuilder = new StringBuilder();
for (int i = 0; i < 26; i++) {
keyBuilder.append(count[i]).append(",");
}
String key = keyBuilder.toString();
// 将字符串插入哈希表
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(s);
}
// 返回哈希表中所有的值
return new ArrayList<>(map.values());
}
}
时间复杂度:
O(N)
,N
是数组长度。O(K)
,K
是字符串平均长度。O(N * K)
。空间复杂度:
O(N * K)
。'a'
到 'z'
映射到第 i
个质数。import java.util.*;
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// 每个字母对应的质数值
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
};
Map<Long, List<String>> map = new HashMap<>();
for (String s : strs) {
long key = 1;
for (char c : s.toCharArray()) {
key *= primes[c - 'a'];
}
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(s);
}
return new ArrayList<>(map.values());
}
}
时间复杂度:
O(N)
。O(K)
。O(N * K)
。空间复杂度:
O(N * K)
。推荐:排序 + 哈希表(解法 1)
优化:计数特征 + 哈希表(解法 2)
进阶:质数乘积(解法 3)
熟练掌握解法 1 和解法 2,可以在面试中快速 AC 并展现对字符串操作和哈希表应用的理解能力!