[LeetCode]56. 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.
Update (2015-08-09):
The signature of the function had been updated to return list<list<string>>
instead of list<string>
, as suggested here. If you still see your function signature return alist<string>
, please click the reload button to reset your code definition.
Subscribe to see which companies asked this question
解法1:前面已经做过题目验证两个字符串是不是互相成为变位词,因此一个简单的思路就是两层循环,判断每两对个词语是否互为变位词,时间复杂度大于O(n^2),会超时Time Limit Exceeded
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { int n = strs.size(); vector< vector<string> > res; vector<int> flag(n, 0); for (int i = 0; i < n; ++i) { if (flag[i] == 1) continue; vector<string> tmp = { strs[i] }; flag[i] = 1; for (int j = i + 1; j < n; ++j) { if (flag[j] == 1) continue; if (isAnagram(strs[i], strs[j])) { tmp.push_back(strs[j]); flag[j] = 1; } } sort(tmp.begin(), tmp.end()); res.push_back(tmp); } return res; } private: bool isAnagram(string s, string t) { int ss = s.size(), ts = t.size(); if (ss != ts) return false; vector<int> v1(26, 0), v2(26, 0); for (int i = 0; i < ss; ++i) { ++v1[s[i] - 'a']; ++v2[t[i] - 'a']; } for (int i = 0; i < 26; ++i) if (v1[i] != v2[i]) return false; return true; } };
解法2:另一个想法是顺序扫描字符串序列,如果发现当前字符串不是以前任意字符串的变位词,则新建vector<string>加入到结果中,同时记录下当前字符串的模式,留待后面进行匹配。这样时间复杂度还是比较高,也会超时Time Limit Exceeded
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { int n = strs.size(); vector< vector<string> > res; vector< map<char, int> > pattSet; for (int i = 0; i < n; ++i) { map<char, int> patt; for (int j = 0; j < strs[i].size(); ++j) ++patt[strs[i][j]]; vector< map<char, int> >::iterator iter1 = find(pattSet.begin(), pattSet.end(), patt); if (iter1 == pattSet.end()) { res.push_back(vector<string>{strs[i]}); pattSet.push_back(patt); } else res[iter1 - pattSet.begin()].push_back(strs[i]); } for (int i = 0; i < res.size(); ++i) sort(res[i].begin(), res[i].end()); return res; } };
解法3:将解法2的vector<map<char, int>>改进。只要将每个字符串排序就可以得知它们是不是互为变位词,因此模式可以存储为string类型,而对应的所有变位词在strs中的下标则存于vector中,因此设计Map为map<string, vector<int>>。
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { int n = strs.size(); vector< vector<string> > res; map<string, vector<int> > m; for (int i = 0; i < n; ++i) { string s = strs[i]; sort(s.begin(), s.end()); m[s].push_back(i); } for (map<string, vector<int> >::iterator iter = m.begin(); iter != m.end(); ++iter) { vector<string> tmp; for (int i = 0; i < iter->second.size(); ++i) tmp.push_back(strs[iter->second[i]]); sort(tmp.begin(), tmp.end()); res.push_back(tmp); } return res; } };