题目链接: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 };