题目
标题和出处
标题:字母异位词分组
出处:49. 字母异位词分组
难度
4 级
题目描述
要求
给定一个字符串数组 strs \texttt{strs} strs,将字母异位词组合在一起。可以按任意顺序返回结果。
字母异位词是将另一个单词或词组的字母重新排列之后得到的单词或词组,原始单词或词组中的每个字母恰好使用一次。
示例
示例 1:
输入:
strs
=
["eat",
"tea",
"tan",
"ate",
"nat",
"bat"]
\texttt{strs = ["eat", "tea", "tan", "ate", "nat", "bat"]}
strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[["bat"],["nat","tan"],["ate","eat","tea"]]
\texttt{[["bat"],["nat","tan"],["ate","eat","tea"]]}
[["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入:
strs
=
[""]
\texttt{strs = [""]}
strs = [""]
输出:
[[""]]
\texttt{[[""]]}
[[""]]
示例 3:
输入:
strs
=
["a"]
\texttt{strs = ["a"]}
strs = ["a"]
输出:
[["a"]]
\texttt{[["a"]]}
[["a"]]
数据范围
- 1 ≤ strs.length ≤ 10 4 \texttt{1} \le \texttt{strs.length} \le \texttt{10}^\texttt{4} 1≤strs.length≤104
- 0 ≤ strs[i].length ≤ 100 \texttt{0} \le \texttt{strs[i].length} \le \texttt{100} 0≤strs[i].length≤100
- strs[i] \texttt{strs[i]} 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);
map.putIfAbsent(key, new ArrayList<String>());
map.get(key).add(str);
}
return new ArrayList<List<String>>(map.values());
}
}
复杂度分析
-
时间复杂度: O ( n k log k ) O(nk \log k) O(nklogk),其中 n n n 是数组 strs \textit{strs} strs 的长度, k k k 是数组 strs \textit{strs} strs 中的字符串的最大长度。需要遍历 n n n 个字符串,每个字符串的排序和更新哈希表共需要 O ( k log k ) O(k \log k) O(klogk) 的时间,总时间复杂度是 O ( n k log k ) O(nk \log k) O(nklogk)。
-
空间复杂度: O ( n k ) O(nk) O(nk),其中 n n n 是数组 strs \textit{strs} strs 的长度, k k k 是数组 strs \textit{strs} strs 中的字符串的最大长度。哈希表需要存储数组 strs \textit{strs} strs 中的全部字符串,需要 O ( n k ) O(nk) O(nk) 的空间。
解法二
思路和算法
根据字母异位词的定义,两个互为字母异位词的字符串包含的字符完全相同,只有顺序可能不同,因此两个互为字母异位词的字符串中,相同字符的出现次数相同。
可以将每个字符的出现次数作为同一组字母异位词的标志,使用哈希表存储每个标志对应的所有字符串,将同一组字母异位词的标志作为哈希表的关键字。
由于每个字符串只包含小写字母,因此可以使用长度为 26 26 26 的数组记录每个字符的出现次数,将该数组转成字符串作为哈希表的关键字。
代码
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String str : strs) {
int[] counts = new int[26];
int length = str.length();
for (int i = 0; i < length; i++) {
counts[str.charAt(i) - 'a']++;
}
String key = Arrays.toString(counts);
map.putIfAbsent(key, new ArrayList<String>());
map.get(key).add(str);
}
return new ArrayList<List<String>>(map.values());
}
}
复杂度分析
-
时间复杂度: O ( n ( k + ∣ Σ ∣ ) ) O(n(k + |\Sigma|)) O(n(k+∣Σ∣)),其中 n n n 是数组 strs \textit{strs} strs 的长度, k k k 是数组 strs \textit{strs} strs 中的字符串的最大长度, Σ \Sigma Σ 是字符集,这道题中字符集为全部小写英语字母, ∣ Σ ∣ = 26 |\Sigma| = 26 ∣Σ∣=26。需要遍历 n n n 个字符串,对于每个字符串,统计每个字符的出现次数需要 O ( k ) O(k) O(k) 的时间,更新哈希表需要 O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣) 的时间,总时间复杂度是 O ( n ( k + ∣ Σ ∣ ) ) O(n(k + |\Sigma|)) O(n(k+∣Σ∣))。
-
空间复杂度: O ( n ( k + ∣ Σ ∣ ) ) O(n(k + |\Sigma|)) O(n(k+∣Σ∣)),其中 n n n 是数组 strs \textit{strs} strs 的长度, k k k 是数组 strs \textit{strs} strs 中的字符串的最大长度, Σ \Sigma Σ 是字符集,这道题中字符集为全部小写英语字母, ∣ Σ ∣ = 26 |\Sigma| = 26 ∣Σ∣=26。哈希表需要存储数组 strs \textit{strs} strs 中的全部字符串以及每组字母异位词的关键字,需要 O ( n ( k + ∣ Σ ∣ ) ) O(n(k + |\Sigma|)) O(n(k+∣Σ∣)) 的空间。