官方题解详细解析
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 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]
仅包含小写字母
题解
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());
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/group-anagrams/solutions/520469/zi-mu-yi-wei-ci-fen-zu-by-leetcode-solut-gyoc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解析
代码逐行解释
```java
class Solution {
```
- 定义了一个名为 `Solution` 的类。
---
```java
public List<List<String>> groupAnagrams(String[] strs) {
```
- 定义了一个公共方法 `groupAnagrams`,它接收一个字符串数组 `strs` 作为参数,并返回一个 `List<List<String>>` 类型的结果。
- 返回值是一个列表,其中每个元素是一个字符串列表,表示一组变位词。
---
```java
Map<String, List<String>> map = new HashMap<String, List<String>>();
```
- 创建一个 `HashMap`,键的类型是 `String`,值的类型是 `List<String>`。
- 这个 `map` 用于存储分组结果,键是排序后的字符串,值是对应的原始字符串列表。
---
```java
for (String str : strs) {
```
- 使用增强的 `for` 循环遍历输入数组 `strs`,每次取出一个字符串 `str`。
---
```java
char[] array = str.toCharArray();
```
- 将当前字符串 `str` 转换为字符数组 `array`,以便进行排序。
---
```java
Arrays.sort(array);
```
- 对字符数组 `array` 进行排序。排序后,所有变位词的字符数组会变成相同的顺序。
---
```java
String key = new String(array);
```
- 将排序后的字符数组 `array` 转换回字符串 `key`。这个 `key` 将作为哈希表的键,用于标识一组变位词。
---
```java
List<String> list = map.getOrDefault(key, new ArrayList<String>());
```
- 从 `map` 中获取与 `key` 对应的列表 `list`。如果 `key` 不存在,则使用 `new ArrayList<String>()` 创建一个新的空列表。
- `getOrDefault` 方法确保即使 `key` 不存在,也不会抛出异常,而是返回默认值。
---
```java
list.add(str);
```
- 将当前字符串 `str` 添加到列表 `list` 中。
---
```java
map.put(key, list);
```
- 将更新后的列表 `list` 重新放入 `map` 中,键为 `key`。
- 如果 `key` 已经存在,则会覆盖原有的值;如果不存在,则会新增一个键值对。
---
```java
}
```
- 结束 `for` 循环。
---
```java
return new ArrayList<List<String>>(map.values());
```
- 从 `map` 中提取所有的值(即所有分组后的列表),并将其转换为 `ArrayList<List<String>>` 类型返回。
- `map.values()` 返回一个包含所有值的集合,`new ArrayList<>()` 将其转换为列表。
---
```java
}
```
- 结束 `groupAnagrams` 方法。
---
```java
}
```
- 结束 `Solution` 类。
---
代码总结
1. **核心思想**:
- 通过将每个字符串排序后的结果作为唯一标识(键),将变位词分组。
- 使用哈希表存储分组结果,键是排序后的字符串,值是对应的原始字符串列表。2. **执行流程**:
- 遍历输入数组,对每个字符串进行排序,生成键。
- 将字符串添加到对应键的列表中。
- 最终返回所有分组列表。3. **复杂度分析**:
- 时间复杂度:`O(n * k log k)`,其中 `n` 是字符串数量,`k` 是字符串最大长度。排序每个字符串需要 `O(k log k)` 时间。
- 空间复杂度:`O(n * k)`,哈希表存储所有字符串的键和列表。4. **适用场景**:
- 适用于需要将变位词分组的场景,如字母异位词分组问题。
---
### **示例**
**输入**:
```java
String[] strs = {"eat", "tea", "tan", "ate", "nat", "bat"};
```
**执行过程**:
1. `"eat"` -> 排序 -> `"aet"` -> 添加到键 `"aet"` 的列表。
2. `"tea"` -> 排序 -> `"aet"` -> 添加到键 `"aet"` 的列表。
3. `"tan"` -> 排序 -> `"ant"` -> 添加到键 `"ant"` 的列表。
4. `"ate"` -> 排序 -> `"aet"` -> 添加到键 `"aet"` 的列表。
5. `"nat"` -> 排序 -> `"ant"` -> 添加到键 `"ant"` 的列表。
6. `"bat"` -> 排序 -> `"abt"` -> 添加到键 `"abt"` 的列表。
**输出**:
```java
[
["eat", "tea", "ate"],
["tan", "nat"],
["bat"]
]
```