題目:
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; } };
