Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
难点:
1、没有读清题意,对易位构词的理解不到位
2、题意不明了。输入为一系列字符串,别与回文记混淆了
3、第一次见到,不是很了解,完全没思路
具体分析:
- 易位构词:两个单词所包含的字符和数量一样,但顺序不同【相当于一组字符的不同序列】
- 判断两个单词是否为anagram的方法
- 法一:使用哈希表:key为字符,value为出现的次数,若两个单词构成的hashmap相同,那么就是anagram。实现起来就是用一个单词构建hashmap,然后用另一个单词对前面的hashmap中的字符逐个去除,最后如果hashmap为空,则返回true。该方法的时间复杂度为O(m+n),m和n分别为另两个单词的长度,而空间复杂度为O(字符集的大小)。
- 法二:将两个单词排序,若排序后的结果相同,说明两个单词是anagram。该方法的时间复杂度取决于排序算法,一般排序算法时间复杂度为O(nlogn),如果字符集足够小,也可以用线性排序算法。
- 总体而言,若判断两个单词是否为anagram,方法一要直接简单一些。
- 对于本题,是在很多字符串里面按照anagram分类,若使用hashmap的方法,两两匹配,在分组时会比较麻烦;而对于法二使用排序算法,其优势在于可以使用排序后的字符串作为一个key,即一个易位构词类的ID。这样一来,只需要对每个字符串排序,然后建立hashmap,key为排序后的串,value为所有属于这个key类的字符串【灵活一点,可以用字符串数组的索引表示】,这样就可以进行简单的分类。若有n个字符串,字符串最大空间为k,那么该算法的时间复杂度为O(nklogk),其中O(klogk)是对每个字符串进行排序(若用线性算法也可以提高),空间复杂度为O(nk),即hashmap的大小。
- 根据返回值,最后还要对hashmap进行整理。
我理解之后提交的代码:
1 #include "stdafx.h" 2 #include <vector> 3 #include <string> 4 #include <map> 5 #include <algorithm> 6 #include <iostream> 7 using namespace std; 8 9 class Solution 10 { 11 public: 12 vector<string> anagrams(vector<string> &strs) 13 { 14 map<string,vector<int>> exists; 15 for(int index =0 ; index < strs.size(); index++)//!!!边界 16 { 17 string s;//sort()会改变字符串,故需要临时变量存储 18 s = strs[index]; 19 sort(s.begin(), s.end()); 20 21 exists[s].push_back(index); //直接插入即可 22 23 } 24 vector<string> result; 25 for(auto const &ip : exists) 26 { 27 if(ip.second.size() > 1)//等于1,没有易位构词;注意表达方式!!! 28 { 29 for(auto const &it : ip.second) 30 result.push_back(strs[it]); 31 } 32 } 33 34 //for(auto it : result) 35 // cout << it << " "; 36 //cout << endl; 37 return result; 38 } 39 }; 40 int main() 41 { 42 Solution sol; 43 string data[] ={"tea","and","ate","nad","eat","dna","dan","tt"}; 44 vector<string> test(data,data+8); 45 sol.anagrams(test); 46 47 return 0; 48 }
网上另一种解法,虽然也能输出,但是,相同易位构词并不会在一类全部输出之后,再输出另一类;但它需要的存储空间比较小
1 class Solution { 2 public: 3 vector<string> anagrams(vector<string> &strs) 4 {//网上代码 5 string s; 6 map<string, int> anagram; 7 vector<string> res; 8 for (int i = 0; i < strs.size(); ++i) 9 { 10 s = strs[i]; 11 sort(s.begin(), s.end()); 12 if (anagram.find(s) == anagram.end()) 13 { 14 anagram[s] = i;//第一次出现此类易位构词 15 } 16 else 17 { 18 if (anagram[s] >= 0) 19 {//此类第二次出现,将第一次输出 20 res.push_back(strs[anagram[s]]); 21 anagram[s] = -1; 22 } 23 //在本类已存在过的情况下[已置为-1],会输出所有,包括第二次输出的 24 res.push_back(strs[i]); 25 } 26 } 27 return res; 28 } 29 };