# [49. Group Anagrams](https://leetcode.com/problems/group-anagrams/)
# 思路
题目要求找出字符串数组里的anagram(同字母异序词)，所有的字母都是小写字母。     
如何判断两个字符串是否是anagram呢，有两种方法:
1. 先排序再判断排序后的字符串是否相等；
2. 遍历一遍，然后用一个数组记录26个字母每个字母出现的次数，再比较这个次数（类似桶排序）。    

如果方法1使用桶排序的话其实两种方法就是差不多的了。    
解决了如何判断的问题，算法思路就清晰了:    
对strs中的每个字符串的副本str，对其进行排序（可以使用桶排序也可使用现成的sort），然后用一个hash表mp来记录这个str是否在以前出现过。
若`mp[str] == 0`则说明没有出现过；否则则出现过，mp[str]的值代表最终返回结果数组（即代码中的res）中对应元素的下标加一。    

若strs中有n个字符串，每个字符串长度平均为m，则桶排序时间复杂度为O(m)，如果使用的是unordered_map（对应hash）则查找复杂度O(1)，所以总体时间复杂度O(mn)。

注意: unordered_map（对应hash）比map（对应红黑树）快一些，所以使用map的时候如果追求时间复杂度则一律使用unordered_map。   

# C++
``` C++
class Solution {
private:
    string count_sort(const string &str){ // 桶排序，返回str排序后的副本
        int count[26] = {0};
        for(char c: str) count[c - 'a']++;
        string res;
        for(int i = 0; i < 26; i++)
            res.append(count[i], i + 'a'); // 在res后面加上count[i]个字符 i + 'a'
        return res;
    }
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>>res;
        unordered_map<string, int>mp;
        int n = strs.size();
        for(int i = 0; i < n; i++){
            string str = count_sort(strs[i]); // 使用桶排序理论上会快一些
            // string str = strs[i];
            // sort(str.begin(), str.end());
            
            int tmp = mp[str];
            if(tmp == 0) { // 没出现过
                res.push_back(vector<string>(1, strs[i]));
                mp[str] = res.size(); // map[str]的值代表res对应元素的下标加一
            }
            else
                res[tmp - 1].push_back(strs[i]);
        }
        return res;
    }
};
```
