Group Anagrams
Solution 1
一开始我把之前的置换问题的思路套进去了,但是发现好像不需要那么复杂。回文字符串其实很好判断:组成字符的个数相同就可以了。所有可以利用这个特性大大压缩时间复杂度。
我的基本思路很简单:将每个字符串的字符计数形式化成一个哈希键,然后检查所有的字符串往哈希表里面塞就可以了。最后结果遍历整个哈希表就可以了。
但是!!!但是!!!因为我没想出来怎么把数字(超过10)转成一个字符串来做键,加在一起或者乘在一起也不行,C++里面的将数组作为键我查了好久,最后放弃了,这部分使用官方题解实现了……
其实在Python里面,list作为一个键和容易,C++就很麻烦。
- 时间复杂度: O ( N M ) O(NM) O(NM),其中 N N N为输入的字符串个数, M M M为输入的字符串的最坏长度
- 空间复杂度: O ( N M ) O(NM) O(NM),其中 N N N为输入的字符串个数, M M M为输入的字符串的最坏长度
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> ans;
// 官方题解给出的哈希函数
auto arrayHash = [fn = hash<int>{}] (const array<int, 26>& arr) -> size_t {
return accumulate(arr.begin(), arr.end(), 0u, [&](size_t acc, int num) {
return (acc << 1) ^ fn(num);
});
};
unordered_map<array<int, 26>, vector<string>, decltype(arrayHash)> check(0, arrayHash);
for (auto str: strs) {
array<int, 26> count{};
for (auto c: str) { count[c - 97]++; }
check[count].emplace_back(str);
}
for (auto item: check) {
ans.emplace_back(item.second);
}
return ans;
}
};
Solution 2
Solution 1的Python实现。注意list不能直接用来做键(因为mutable),所以需要小小操作一下下。
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
ans = dict()
for sstr in strs:
count = [0] * 26
for c in sstr: count[ord(c) - 97] += 1
if repr(count) not in ans: ans[repr(count)] = [sstr]
else: ans[repr(count)].append(sstr)
return ans.values()