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: All inputs will be in lower-case.
思路见注释。
tips:这次终于肯定,LeetCode把你的空间复杂度也算在时间里!之前开了100W的数组,运行时间150ms,后来换成1W的数组,运行时间49Ms,后来换成vector,最大程度节省空间,也是49Ms了。
class Solution {
public:
/*
用 map 存放结果。
对于每个词,用一个 int 型变量作为它的key,然后在map中寻找是否有这个标记。
如果有,将这个词加入到map中这个标记的后面;若没有,新增加这个key
*/
vector<string> key;
//不能用二进制,不然类似 boo,bob这样的没法识别
//如果直接根据每一位的字母大小,用1左移再相加,这样的hash会出问题,比如huh 和 tit
//用 vector 来节省空间开销
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string> > res;
map<string,vector<string> > m;
int len = strs.size();
//初始化key数组
for(int i=0;i<len;i++)
{
string t_str = "";
t_str += "00000000000000000000000000000000";
key.push_back(t_str);
}
for(int i=0;i<len;i++)
{
int t_len = strs[i].length();
for(int j=0;j<t_len;j++)
{
key[i][strs[i][j]-'a'] += 1;
}
}
//进行遍历
map<string,vector<string> >::iterator it;
for(int i=0;i<len;i++)
{
it = m.find(key[i]);
if(it != m.end()) //已经有了
{
it->second.push_back(strs[i]);
}
else
{
vector<string> tmp;
tmp.clear();
tmp.push_back(strs[i]);
m.insert(make_pair(key[i],tmp));
}
}
//转化结果
it = m.begin();
while(it != m.end())
{
res.push_back(it->second);
it++;
}
return res;
}
};
solution区还有个人用Java写的,用了素数表映射,据称运行时间击败了100%的人(这个有待考究hh)
public static List<List<String>> groupAnagrams(String[] strs) {
int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103};//最多10609个z
List<List<String>> res = new ArrayList<>();
HashMap<Integer, Integer> map = new HashMap<>();
for (String s : strs) {
int key = 1;
for (char c : s.toCharArray()) {
key *= prime[c - 'a'];
}
List<String> t;
if (map.containsKey(key)) {
t = res.get(map.get(key));
} else {
t = new ArrayList<>();
res.add(t);
map.put(key, res.size() - 1);
}
t.add(s);
}
return res;
}