LeetCode(49)Anagram

题目如下:

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;
    }
};



参考资料:

(1) Yu's Coding Garden

你可能感兴趣的:(LeetCode,字符串)