携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
- 示例 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] 仅包含小写字母
方法一:排序(Java)
字母相同,但排列不同的字符串,排序后都一定是相同的。因为每种字母的个数都是相同的,那么排序后的字符串就一定是相同的。
这里可以利用 stream 的 groupingBy 算子实现直接返回结果
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());
}
}
n:strs中字符串的数量
k:strs中字符串的最大长度
时间复杂度:O(nklogk)
空间复杂度:O(nk)
方法二:计数(Go)
由于互为字母异位词的两个字符串包含的字母相同,因此两个字符串中的相同字母出现的次数一定是相同的,故可以将每个字母出现的次数使用字符串表示,作为哈希表的键。
由于字符串只包含小写字母,因此对于每个字符串,可以使用长度为 2626 的数组记录每个字母出现的次数。
用26位的数组存储字母出现次数,map中可以以数组作为key
func groupAnagrams(strs []string) (ans [][]string) {
// 用数组记录异位词
mp := make(map[[26]int][]string)
for _, str := range strs {
cnt := conv(str)
if _, ok := mp[cnt]; !ok {
mp[cnt] = []string{}
}
mp[cnt] = append(mp[cnt], str)
}
for _, val := range mp {
ans = append(ans, val)
}
return ans
}
func conv(s string) (ret [26]int) {
for _, char := range s {
ret[char - 'a']++
}
return
}