题目链接:Anagrams

Given an array of strings, return all groups of strings that are anagrams.

Note: All inputs will be in lower-case.

这道题的要求是给定字符串数组,返回能构成异构的所有字符串。

anagram,即异构,意思是指由颠倒字母顺序组成的单词,比如“live”颠倒字母顺序会变成“evil”(不好好活着就会成恶魔),因此“live”和“evil”就构成异构。异构构词法有一个特点:单词里的字母的种类和数目没有改变,只是改变了字母的排列顺序。

知道了题意,那么思路就来了,对每个字符串hash,然后返回hash值数目超过1的所有字符串。在hash时,字符串中字母顺序不同的字符串应该有同样的hash值,因此可以考虑先对字符串的字符排序。

这里使用map进行hash处理,key为排序后的字符串,value为字符串的第一次出现的位置,如果重复出现,则value置为-1。这样当key第一次出现时,记录字符串的位置到value中,而当同样的key又出现的时候,将之前的字符串也记录下来。

时间复杂度:O(n*l*logl)(l为字符串长度)

空间复杂度:O(n*l)

 1 class Solution
 2 {
 3 public:
 4     vector<string> anagrams(vector<string> &strs)
 5     {
 6         vector<string> vs;
 7         
 8         map<string, int> m;
 9         for(int i = 0; i < strs.size(); ++ i)
10         {
11             string s = strs[i];
12             sort(s.begin(), s.end());
13             if(m.find(s) == m.end())
14                 m[s] = i;
15             else
16             {
17                 if(m[s] >= 0)
18                 {
19                     vs.push_back(strs[m[s]]);
20                     m[s] = -1;
21                 }
22                 vs.push_back(strs[i]);
23             }
24         }
25         
26         return vs;
27     }
28 };

考虑到是字符串中的子串进行排序,因此,可以按计数排序的思路,将排序的时间复杂度降为O(l)。

时间复杂度:O(n*l)(l为字符串长度)

空间复杂度:O(n*l)

 1 class Solution
 2 {
 3 public:
 4     vector<string> anagrams(vector<string> &strs)
 5     {
 6         vector<string> vs;
 7         
 8         unordered_map<string, int> m;
 9         for(int i = 0; i < strs.size(); ++ i)
10         {
11             string s = sortStr(strs[i]);
12             if(m.find(s) == m.end())
13                 m[s] = i;
14             else
15             {
16                 if(m[s] >= 0)
17                 {
18                     vs.push_back(strs[m[s]]);
19                     m[s] = -1;
20                 }
21                 vs.push_back(strs[i]);
22             }
23         }
24         
25         return vs;
26     }
27 private:
28     string sortStr(string &s)
29     {
30         vector<int> vi(26, 0);
31         for(int i = 0; i < s.size(); ++ i)
32             ++ vi[s[i] - 'a'];
33         
34         string res = "";
35         for(int i = 0; i < vi.size(); ++ i)
36             while(vi[i] --)
37                 res += (char)(i + 'a');
38         return res;
39     }
40 };