[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:

  1. For the return value, each inner list's elements must follow the lexicographic order.
  2. 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;
    }
};
原文地址:https://www.cnblogs.com/aprilcheny/p/4935127.html