Leetcode 49. Group Anagrams (242.Valid Anagram)
valid Anagram
Given two strings s and t, write a function to determine if t is an anagram of s.
For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
Note:
You may assume the string contains only lowercase alphabets.
Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
1、题目分析
解法一:使用一个数组,将a-z这26个字母的出现情况保存下来。第一个字符串出现的单词加一,第二个字符串出现的单词减一。最后保存26的字母的数组为全0,则两个字符串相等。
1 class Solution { 2 public: 3 bool isAnagram(string s, string t) { 4 if(s.size()!=t.size()){ 5 return false; 6 } 7 vector<int> flag(26,0); 8 for(int i = 0;i<s.size();i++){ 9 flag[s[i]%26]++; 10 flag[t[i]%26]--; 11 } 12 for(int i = 0;i<26;i++){ 13 if(flag[i]!=0){ 14 return false; 15 } 16 } 17 return true; 18 } 19 };
Anagram group
这个题目要更复杂一些,需要比较多个字符串,并进行分类排序。
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.
1、题目分析
超时解法:
1、使用sort函数将每个单词进行排序。 O( N*log(m))
2、然后遍历这个字符串数组,申请一个一维整型数组,将相同的单词编上相同的数字。 O(1)
3、申请一个二维数组 vector<vector<string>>把相同编号的单词放到同一个一维数组中。 O(N*logN)
4、对每一个一维数组进行排序。最终返回结果。 O(N)~O(logN)
时间复杂度分析:sort函数采用快速排序实现,假设n个单词,每个单词m个字母。m比较小,n比较大。
从上面的分析可知,2.遍历数组过程中判断某个单词是新单词还是以前出现过的耗时最长。
1 class Solution { 2 public: 3 vector<vector<string>> groupAnagrams(vector<string>& strs) { 4 int num = strs.size(); 5 vector<string> strscopy; 6 vector<string> resultLine; 7 vector<string> temp; 8 vector<int> flag(strs.size(),-1); 9 10 strscopy.assign(strs.begin(),strs.end()); 11 12 //对每个单词排序 13 for(int i = 0;i<num;i++){ 14 sort (strs[i].begin(), strs[i].end()); 15 } 16 //sort(strs.begin(),strs.end()); 17 //使用temp记录相同的元素大类,使用flag记录每个单词摆放的位置。O(m*n) 18 for(int i = 0;i<num;i++){ 19 int tag = -1; 20 int j; 21 for(j = 0;j<temp.size();j++){ 22 if(strs[i]==temp[j]){ 23 tag = j; 24 } 25 } 26 if(tag!=-1){ 27 flag[i] = tag; 28 }else{ 29 temp.push_back(strs[i]); 30 flag[i] = temp.size()-1; 31 } 32 tag = -1; 33 } 34 vector<vector<string>> result(temp.size(),resultLine); 35 //O(n) 36 for(int i = 0;i<strs.size();i++){ 37 result[flag[i]].push_back(strscopy[i]); 38 } 39 //O(m)*O(sort) 40 for(int i = 0;i<result.size();i++){ 41 sort(result[i].begin(),result[i].end()); 42 } 43 return result; 44 45 } 46 };
改进解法:
使用unordered_map结构来实现单词分类。上述过程改进为
1、使用sort函数将每个单词进行排序。 O( N*log(m))
2、key值保存排完序的单词,value为字符串数组。
3、对每个单词排序 O(log(N))
1 vector<vector<string>> result; 2 unordered_map<string, vector<string>> hashmap; 3 //使用sort函数对每个单词排序 4 for(const auto& i : strs){ 5 string s = i; 6 sort(s.begin(), s.end()); 7 //使用map结构进行保存 8 hashmap[s].push_back(i); 9 } 10 for(const auto& i : hashmap){ 11 //i.second表示hashmap的value值 12 vector<string> s = i.second; 13 sort(s.begin(), s.end()); 14 result.push_back(s); 15 } 16 return result;