LeetCode | Anagrams

来源:互联网 发布:ps4最终幻想10淘宝 编辑:程序博客网 时间:2024/05/22 15:31

Given an array of strings, return all groups of strings that are anagrams.

Note: All inputs will be in lower-case.

题目解析:

题目的意思是给一个String数组,找出其中由相同字母组成的单词。

例如:

S = ["abc", "bca", "bac", "bbb", "bbca", "abcb"]

答案为:

["abc", "bca", "bac", "bbca", "abcb"]

只有"bbb"没有相同字母组成的单词。


所以该题实际上不难,把每一个String用一种约定的标准方式表达出来即可,我用的标准是,按字母排序。

例如:

"abc" = "abc",

"bca" = "abc",

"bac" = "abc


方案一:

思路:用map<string, int>记录排序后的字符串以及首次出现的位置。
1. 从strs的第一个元素开始遍历,首先对string进行排序得到tmps;
2. 在map里查找tmps;
3. 若不存在,将tmps以及该元素的下标存入map<string ,int>;
4. 若存在,首先将第一次出现tmps时的原始字符串存入结果solution,即strs[map[tmps]],并将map[tmps]设置为-1(防止下次再存),再将该字符串本身存入结果solution;
5. 重复以上1-4步,直到遍历结束。

class Solution {public:    vector<string> anagrams(vector<string> &strs) {        string s;        map<string, int> anagram;        vector<string> res;        for (int i = 0; i < strs.size(); ++i) {            s = strs[i];            sort(s.begin(), s.end());            if (anagram.find(s) == anagram.end()) {                anagram[s] = i;            } else {                if (anagram[s] >= 0) {                    res.push_back(strs[anagram[s]]);                    anagram[s] = -1;                }                res.push_back(strs[i]);            }        }        return res;    }};


方案二:

如果只是颠倒顺序,但字符的个数不变,那么我们可以通过计数来判断。设置一个hash[26]个字符的数组,如果两个字符的hash[i]都相等,证明两个是Anagram(回文构词法)。

class Solution {public:    struct StringHash    {        char hash[26];        //将传进来的字符串分解,放入hash数组中。然后以这个数组当关键字,如果两个字符串的hash数组相等,证明是回文构词        StringHash(const string& str)        {            fill(hash, hash+26, 0);            for(auto& ch : str)                ++ hash[ch - 'a'];        }        //定义操作!这个很关键,定义什么小于号的意义        bool operator<(const StringHash& sh) const        {            for(size_t i = 0; i < 26; ++i)                if ( this->hash[i] < sh.hash[i] )                    return true;                else if ( this->hash[i] > sh.hash[i] )                    return false;            return false;        }    };    vector<string> anagrams(vector<string> &strs)    {        map<StringHash, vector<vector<string>::iterator>>  hash_map;        for(auto iter=begin(strs); iter != end(strs); ++iter)            hash_map[StringHash(*iter)].push_back(iter);        vector<string> ret;        for(auto hsm : hash_map)            if (hsm.second.size() >= 2)                for(auto i : hsm.second)                    ret.push_back(*i);        return ret;    }};


方案三:

根据上面的启发:为每一个字符串都构建一个map映射。最后输出的时候,只有将个数大于2的输出。

我们完全可以构造一个map<string,vector<string> >。第一个表示排过序后的字符串,将所有排序后与第一个字符串相等的字符串,都放入第二个变量的容器当中。

class Solution {public:    vector<string> anagrams(vector<string> &strs) {        // Start typing your C/C++ solution below        // DO NOT write int main() function        int sz = strs.size();        vector<string> res;        if(sz<2) return res;        unordered_map<string, vector<string> > Map;                 for(int i=0; i<sz; i++) {            string s = strs[i];            sort(s.rbegin(), s.rend(), greater<char>());\\for fun            Map[s].push_back(strs[i]); \\alert. different form java. no need to create a vector.                   }                unordered_map<string, vector<string> >::iterator it = Map.begin();                for(; it!= Map.end(); it++) {            vector<string> & v = (*it).second; \\standard way to iterate map.            if( v.size()>=2) {                res.insert(res.end(), v.begin(), v.end());            }        }        return res;    }};




0 0
原创粉丝点击