【LeetCode】49. Group Anagrams
题目:
Given an array of strings, group anagrams together.
For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"]
, Return:
[ ["ate", "eat","tea"], ["nat","tan"], ["bat"] ]
Note:
- For the return value, each inner list's elements must follow the lexicographic order.
- All inputs will be in lower-case.
提示:
这道题要把所有字母组成相同的单词归为一类。因此我们可以把每个字母都进行排序,然后利用一个hash_map保存。即以排序后的结果作为键,map的值可以是一个set,把排序前的结果插入到set当中。由于set的底层实现利用了平衡二叉搜索树,所以插入以后的元素是已经排好序的。这样归类就完成了。
代码:
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { vector<vector<string>> res; if (strs.empty()) { return res; } unordered_map<string, multiset<string>> um; for (string str : strs) { string tmp = str; sort(tmp.begin(), tmp.end()); um[tmp].insert(str); } for (auto m : um) { vector<string> sol(m.second.begin(), m.second.end()); res.push_back(sol); } return res; } };
实际上,由于对单词排序时,题目已经限定了单词只可能是26个小写字母组成的,所以我们可以使用计数排序进一步加快算法的速度(排序部分速度从O(nlogn)变为O(n)),代码如下:
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { vector<vector<string>> res; if (strs.empty()) { return res; } unordered_map<string, multiset<string>> um; for (string str : strs) { string tmp = strSort(str); um[tmp].insert(str); } for (auto m : um) { vector<string> sol(m.second.begin(), m.second.end()); res.push_back(sol); } return res; } string strSort(string s) { vector<int> count(26, 0); for (int i = 0; i < s.length(); ++i) { ++count[s[i] - 'a']; } string res = ""; for (int i = 0; i < 26; ++i) { while (count[i]--) { res += ('a' + i); } } return res; } };