给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
提示:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i]
仅包含小写字母
整体思路
字母异位词的字符重新排列后完全相同。例如,"eat" 和 "tea" 排序后都是 "aet"。我们可以利用这一特性:
- 排序后的字符串作为键 :将每个字符串排序后得到一个键。
- 哈希表分组 :用哈希表存储所有字符串,键是排序后的字符串,值是原始字符串的列表。
这样,所有字母异位词会被归到同一个键下,最终直接返回哈希表的值列表即可。
代码步骤分解
1. 初始化哈希表
Map<String, List<String>> map = new HashMap<>();
- 作用 :创建一个哈希表,键是排序后的字符串,值是原始字符串的列表。
- 关键点 :
HashMap<String, List<String>>
表示键是String
,值是List<String>
类型。
2. 遍历每个字符串
for (String str : strs) {
// 处理每个字符串
}
- 作用 :遍历输入的字符串数组
strs
中的每一个字符串str
。 - 语法 :这是 Java 的增强型
for
循环,等价于for (int i = 0; i < strs.length; i++) { String str = strs[i]; ... }
。
3. 字符串转换为字符数组并排序
char[] array = str.toCharArray();
Arrays.sort(array);
- 作用 :将字符串转为字符数组并排序。
- 关键函数 :
str.toCharArray()
:将字符串转为char[]
。例如,"eat" →['e', 'a', 't']
。Arrays.sort(array)
:对字符数组排序。例如,['e','a','t']
→['a','e','t']
。
4. 生成哈希表的键
String key = new String(array);
- 作用 :将排序后的字符数组转回字符串,作为哈希表的键。
- 示例 :排序后的
['a','e','t']
→"aet"
。
5. 更新哈希表
List<String> list = map.getOrDefault(key, new ArrayList<>());
list.add(str);
map.put(key, list);
- 作用 :将当前字符串添加到对应的分组列表中。
- 关键函数 :
map.getOrDefault(key, new ArrayList<>())
:- 如果键
key
存在,返回对应的列表。 - 如果键不存在,返回一个空的
ArrayList
。
- 如果键
list.add(str)
:将当前字符串添加到列表。map.put(key, list)
:将更新后的列表存回哈希表。
6. 返回结果
return new ArrayList<>(map.values());
- 作用 :将哈希表中的所有值(分组列表)转换为一个
ArrayList
。 - 关键点 :
map.values()
返回所有分组的列表集合,new ArrayList<>()
将其转为列表的列表。
示例模拟
输入:["eat", "tea", "tan", "ate", "nat", "bat"]
原始字符串 | 排序后的键 | 哈希表操作 |
---|---|---|
"eat" | "aet" | 添加到键 "aet" 的列表 → ["eat"] |
"tea" | "aet" | 添加到键 "aet" 的列表 → ["eat", "tea"] |
"tan" | "ant" | 添加到键 "ant" 的列表 → ["tan"] |
"ate" | "aet" | 添加到键 "aet" 的列表 → ["eat", "tea", "ate"] |
"nat" | "ant" | 添加到键 "ant" 的列表 → ["tan", "nat"] |
"bat" | "abt" | 添加到键 "abt" 的列表 → ["bat"] |
最终结果:[["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]
关键函数总结
函数/语法 | 作用 | 示例 |
---|---|---|
| 字符串转字符数组 |
|
| 对数组排序 |
|
| 字符数组转字符串 |
|
| 安全获取键值,避免空指针 |
|
| 获取哈希表中所有值的集合 | 返回所有分组的列表 |
时间复杂度分析
- 排序时间 :每个字符串排序耗时 O(klogk),其中 k 是字符串长度。
- 总时间复杂度 :O(n⋅klogk),其中 n 是字符串数量。
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String str : strs) {
char[] array = str.toCharArray();
Arrays.sort(array);
String key = new String(array);
List<String> list = map.getOrDefault(key, new ArrayList<String>());
list.add(str);
map.put(key, list);
}
return new ArrayList<List<String>>(map.values());
}
}