题目描述:
题号:49
题目描述:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列原单词的所有字母得到的一个新单词。
边界条件:
-
1 <= strs.length <= 104
-
0 <= strs[i].length <= 100
-
strs[i] 仅包含小写字母
示例 :
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
解题思路:
思路一:对每个单词进行排序+哈希表
互为字母异位词的两个字符串的特征:包含的字母相同。
因此想到对两个字符串分别进行排序之后得到的字符串也是相同的。因此可以利用排序后的字符串统计字母异位词:将排序之后的字符串作为哈希表的键,原字符串作为哈希表的值。
K为字符串平均大小,N为字符串数量
时间复杂度:O(N*KlogK):排序算法有KlogK时间复杂度
空间复杂度:O(K*N)
C++
// C++
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
if(strs.size() == 0) {
return {};
}
unordered_map<string, vector<string>> subMap;
for(string &value : strs) {
string key = value;
// 字母异位词根据字符排序后的字符串是相同的
sort(key.begin(), key.end());
// 以排序后的词作为map的key
subMap[key].push_back(value);
}
vector<vector<string>> result;
for(auto item = subMap.begin(); item != subMap.end(); item++) {
result.push_back(item->second);
}
return result;
}
};
go
// go
func groupAnagrams(strs []string) [][]string {
if len(strs) == 0 {
return nil
}
subMap := map[string][]string{}
for _, v := range strs {
vByte := []byte(v)
sort.Slice(vByte, func(i, j int) bool {return vByte[i] < vByte[j]})
sortKey := string(vByte)
subMap[sortKey] = append(subMap[sortKey], v)
}
result := make([][]string, 0, len(subMap))
for _, v := range subMap {
result = append(result, v)
}
return result
}
思路二:哈希
第二种思路是将字符串中会出现的26个小写字母像哈希映射一样映射到一个string对象中,映射相同的字符串具有相同数量的每种字母,因此必定是字母异位词
时间复杂度:O(K*N)
空间复杂度:O(K*N)
C++
// C++
class Solution{
private:
string getKeyHash(const string &str) {
// 统计每个字符串中的每个字符出现的数量
string Hash(26, 0);
for(const char &ch : str) {
Hash[ch - 'a']++;
}
return Hash;
}
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
if(strs.size() == 0) {
return {};
}
unordered_map<string, vector<string>> subMap;
for(const auto &str : strs) {
subMap[getKeyHash(str)].push_back(str);
}
vector<vector<string>> result;
for(const auto &item : subMap) {
result.push_back(item.second);
}
return result;
}
};
go
// go
func groupAnagrams(strs []string) [][]string {
if len(strs) == 0 {
return nil
}
subMap := make(map[string][]string)
for _, str := range strs {
key := getKeyHash(str)
subMap[key] = append(subMap[key], str)
}
var result [][]string
for _, group := range subMap {
result = append(result, group)
}
return result
}
func getKeyHash(str string) string {
// 统计每个字符串中的每个字符出现的数量
hash := make([]int, 26)
for _, ch := range str {
if ch >= 'a' && ch <= 'z' {
hash[ch-'a']++
}
}
// 将字符计数转换为字符串,用作哈希键
var sb strings.Builder
for _, count := range hash {
sb.WriteString(strconv.Itoa(count))
sb.WriteString("#")
}
return sb.String()
}