0%

Leetcode 每日一题6 Group Anagrams

题意

给一个数组,起元素为只包含英文小写字母的单词。

要求分组输出使用了相同字符构造的单词,比如tea和eat就是同类单词。

思路

将所有的单词遍历一遍,将同类单词放到同一个位置中去,关键是这个映射要怎么实现。对于一个长度为m的单词,我们可以用O(m)的时间遍历出各字符的使用次数。接着,我们将其转化成字符串,对于某个字符,其出现次数可以编码成cnt + char,然后按照英文字母表顺序连接起来。比如,teaa编码成2a1e1t。

上面的编码使用了一个优化,即对于出现次数的0的字母,不编码到字符串中。

假如追求极致,还可以对编码继续优化。

  • 对于出现次数为1的字母,可以不写上cnt。比如teaa可以写成2aet。
  • 当cnt很大时,可以使用整形来表示。比如250,使用char来表示需要3个字节,使用整形只要1个字节。

编码是个很有趣的知识点,上面的编码方式似乎都有专门的名称,以后有空的话专门写篇博客总结一下,这里留个坑:)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> v;
unordered_map<string, vector<string>> m;
for (auto i: strs) {
m[hashWord(i)].push_back(i);
}
for (auto it: m) {
v.push_back(it.second);
}
return v;
}
string hashWord(string s) {
vector<int> cnt(26, 0);
for (int i = 0; i < s.length(); i++) {
cnt[s[i] - 'a']++;
}

string hash;
for (int i = 0; i < 26; i++) {
if (!cnt[i])
continue;
hash += string(cnt[i], 'a' + i);
}
return hash;
}
};