一、题目描述
1.1 题目
-
字母异位词分组
-
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
-
说明:
(1)所有输入均为小写字母。
(2)不考虑答案输出的顺序。 -
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
1.2 知识点
- 哈希表
1.3 题目链接
二、解题思路
2.1 自研思路
对于这道题我的解题思路跟官方提供的解题思路中的解法一:排序数组分类是相似的。在开始的时候其实我想使用对每个字符串进行哈希的方式,然后将其映射到对应的哈希表中,然后以 O(1) 的时间复杂度来对其进行处理,但是在尝试的过程中遇到了一些小的问题,所以改变思路,对每一个字符串进行排序后,使异位词变为同位词,然后将其作为 Map 的键来存储,需要注意的是其实我们没有必要在 HashMap 中将所有的字符串再作为值来重复存储,只需要将其存放到结果列表中,然后将 HashMap 中的键设置为同位词,值设置为该同位词在结果列表中的下标即可,然后当确定一个异位词的分组后将其直接插入到对应的结果列表中即可。但是因为这种方式需要对每一个字符串都要进行排序,所以总体的时间复杂度为 O(NKlogK),其中当我们遍历每个字符串时,外部循环具有的复杂度为 O(N),然后,我们在 O(KlogK) 的时间内对每个字符串排序。
2.2 示例思路
官方的示例中还提供了一种解题的思路,即不对每个字符串进行排序,而是仅统计每个字符串中每个字符出现的次数,因为当且仅当字符计数(每个字符的出现次数)相同时,两个字符串是字母异位词。所以,可以将 HashMap 中的键转换为 #0#0#0#… 这种形式,即对于 abbccc 字符串其存储时的键为 #1#2#3#0#0#… ,且在这种解题思路下的时间复杂度仅为 O(NK) 。
三、实现代码
3.1 自研实现
class Solution {
private String sortString(String s) {
char[] cs = s.toCharArray();
Arrays.sort(cs);
return new String(cs);
}
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
HashMap<String, Integer> hashMap = new HashMap<>();
for(String str : strs){
String s = sortString(str);
Integer index = hashMap.get(s);
if(index == null){
List<String> list = new ArrayList<>();
list.add(str);
res.add(list);
hashMap.put(s, res.size()-1);
} else
res.get(index).add(str);
}
return res;
}
}
3.2 示例代码
class Solution {
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());
}
}