LC49
给定一个字符串数组 strs,请你将所有是“字母异位词”的字符串组合在一起。最终结果可以按任意顺序返回
- 要对字母异位词进行分组,首先需要一个方法来“识别”它们。也就是说,需要找到一种方式,让所有字母异位词都拥有一个相同的“标识”或“签名”,而不同的字母异位词则拥有不同的标识
- 既然字母异位词只是字符排列顺序不同,那么它们共同的属性就是:所包含的字符种类和每种字符的数量是相同的
排序字符串 (Sorted String):
如果两个字符串是字母异位词,那么将它们各自的字符排序后,得到的字符串将是完全相同的
算法步骤:
- 创建一个哈希表 (
std::unordered_map)- 键 (Key): 用来识别字母异位词的“标识”,这里是排序后的字符串
- 值 (Value): 是一个字符串列表 (
std::vector<std::string>),用于存储所有具有相同标识的原始字符串
- 遍历输入的字符串数组 strs 中的每个字符串 s
- 将
s复制一份,得到key_s key_s进行排序 (例如使用std::sort)- 将原始字符串
s添加到哈希表中以key_s为键对应的字符串列表中
- 将
- 遍历哈希表,将其所有值 (即每个字符串列表) 收集起来,形成最终的结果列表
class Solution {
public:
std::vector<std::vector<std::string>> groupAnagrams(std::vector<std::string>& strs) {
// 哈希表:键是排序后的字符串 (作为标识),值是原始字符串的列表
std::unordered_map<std::string, std::vector<std::string>> anagram_groups;
// 遍历输入的每个字符串
for (const std::string& s : strs) {
// 创建一个副本,用于排序作为键
std::string key = s;
// 对副本进行排序,这将是字母异位词的唯一标识
std::sort(key.begin(), key.end());
// 将原始字符串添加到以排序后的字符串为键的列表中
anagram_groups[key].push_back(s);
}
// 收集结果:将哈希表中所有值 (即每个组的字符串列表) 放入最终结果
std::vector<std::vector<std::string>> result;
for (auto const& [key, val] : anagram_groups) { // C++17 结构化绑定,方便遍历 map
result.push_back(val);
}
return result;
}
};
时间复杂度分析:
- 假设输入数组
strs包含N个字符串 - 每个字符串的平均长度为
L - 遍历
N个字符串: O(N) - 对每个字符串进行排序: std::sort 对长度为 L 的字符串排序的时间复杂度是 O(LlogL)
- 总的时间复杂度是 N 乘以单次操作的时间,即 O(N⋅LlogL)
空间复杂度分析:
- 哈希表
anagram_groups最多会存储N个键值对 (每个字符串独立成组) - 键是排序后的字符串,长度为
L。值是原始字符串的列表,总共存储了所有N个原始字符串,总长度为 N⋅L - 空间复杂度是 O(N⋅L)