题目如下:
Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
分析如下:
之前遇到过类似的题目。处理的方法是,把每个词都sort一下,sort之后的结果作为key存入map中,比如ate在sort之后是aet,存入了map,下次再遇到一个词,如tea, 则sort之后发现map中已经存储过了,说明tea是一个anagram,遍历一遍输入,并且在map中查找当前word的key,只要map中存在当前word的key,就说明当前word是anagram。
这样处理之后,几乎把所有的anagram都找到了,但是第一次存入map中的word还漏掉了。所以再补上就行。
我的代码:
好不容易啊,在非IDE环境下写好一次提交bug free.不过时间运行时间挺长的,居然是332ms。
// 332ms
class Solution {
public:
vector<string> anagrams(vector<string> &strs) {
vector<string> res;
int len = (int)strs.size();
if(len==0)
return res;
map<string, string> string_map;
map<string, string>::iterator string_map_it;
map<string, int> count_map;
map<string, int>::iterator count_map_it;
for(int i=0;i<len;i++){
string each_str=strs[i];
sort(each_str.begin(),each_str.end());
count_map_it=count_map.find(each_str);
if(count_map_it==count_map.end()){
count_map.insert(std::pair<string, int>(each_str,1));
string_map.insert(std::pair<string, string>(each_str,strs[i])); //第一次出现的anagram先存入string_map中,稍后再补上。
}else{
count_map_it->second++;
res.push_back(strs[i]); //当前word是anagram,所以放入输出的vector
}
}
for(string_map_it=string_map.begin();string_map_it!=string_map.end();string_map_it++){ //补充第一次存入string_map的anagram到输出
count_map_it=count_map.find(string_map_it->first);
if( (count_map_it!=count_map.end() ) && ( (count_map_it->second)>1) )
res.push_back(string_map_it->second);
}
return res;
}
};
改进分析:
上面的代码看着不太好的一点是,string_map存在的原因是,使得第一次存入key时,key对应的word不会被弄丢失。这样的开销比较大。看到这里有一个不错的答案。用mp[ss]=-1来做标记,防止第一次存入map的word被反复放入输出。
//208 ms
#include <set>
#include <map>
using namespace std;
class Solution {
public:
vector<string> anagrams(vector<string> &strs) { //测试别人的一个更简洁的版本
vector<string> res;
map<string,int> mp;
for (int i=0;i<strs.size();i++){
string ss = strs[i];
sort(ss.begin(),ss.end());
if (mp.find(ss)!=mp.end()){
res.push_back(strs[i]);
if (mp[ss]!=-1){
res.push_back(strs[mp[ss]]);
mp[ss]=-1;
}
}else{
mp[ss]=i;
}
}
return res;
}
};
update: 2014 -11-28
新写的一版,也还算不是太罗嗦,虽然还是没有上面那版别人写得简洁。
// 228 ms
class Solution {
public:
vector<string> anagrams(vector<string> &strs) {
std::map<string, vector<string> > map1;
std::map<string, vector<string> >::iterator it1;
std::string current_string;
vector<string> result;
for (int i = 0; i < strs.size(); i++) {
current_string = strs[i];
std::sort(current_string.begin(), current_string.end() );
map1[current_string].push_back(strs[i]);
}
for (it1 = map1.begin(); it1 != map1.end(); ++it1) {
if (it1->second.size()>1)
result.insert(result.end(), it1->second.begin(), it1->second.end());
}
return result;
}
};
参考资料: