Anagrams 变位词

Anagrams 可以翻译为变位词,对于英语来说一个英文单词的Anagrams,是把单词的字母顺序作调整从而变成另外的一个单词。还有一个中文的称呼叫做兄弟字符串。

题目源自于leetcode。

题目:Given an array of strings, return all groups of strings that are anagrams.Note: All inputs will be in lower-case.

思路:首先,如何判断两个单词是不是Anagrams。

    最容易想到的办法是排序,把两个单词各自按照字母顺序排序,如果是Anagrams,那么排序之后应该就会是相同的

    一个高效的方法叫素数乘积法,是一个很trick的数学方法。给26个字母中每个字母(题目说了只管小写即可)分配一个素数,分别计算2个字符串的字母的素数的乘积。这样得到的乘积在相乘的时候就是由素数组成,所以因子拆分后也只有这一种分法。因此,Anagrams对应的素数乘积是相等的,非Anagrams对应的素数乘积是不相等的。


    本题是要求返回是Anagrams的一组单词,也就是说,输入数据的若干个单词中,只有一组Anagrams,其他的都是各自无关的单词。那么我应该怎么两两比较之后把唯一的一组相同的单词拿出来呢?很明显,当我发现有两个单词是Anagrams时,这两个单词必定是属于最终Anagrams组里的。当两个单词不是Anagrams时,可能有一个是Anagrams组里的,也可能都是不是组里的。因此,我设立一个anagram的集合,如果当前判断的单词在集合中有一样的,我就认为这个单词,和集合里那个跟它一样的单词,都需要拿来放到Anagrams组里去;如果当前判断的单词在集合里没有,那我认为我现在还无法做出抉择,我就把这个单词放到集合里去,等待后人来判断。

代码一:排序方法

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

代码二:素数乘积法

class Solution {
public:
    const int table[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
    long long compute(string s)
    {
        int n = s.length();
        long long mul = 1;
        for(int i=0;i<n;i++)
        {
            mul *= table[s[i] - 'a'];
        }
        return mul;
    }

    vector<string> anagrams(vector<string> &strs) {
        int n = strs.size();
        map<long long, int> anagram;
        vector<string> groups;
        int i;
        for(i=0;i<n;i++)
        {
            long long tmp = compute(strs[i]);
            if(anagram.find(tmp) == anagram.end())
            {
                anagram.insert(make_pair(tmp, i));
            }
            else
            {
                if(anagram[tmp] >=0 )
                {
                    groups.push_back(strs[anagram[tmp]]);
                    anagram[tmp] = -1;
                }
                groups.push_back(strs[i]);
            }
        }
        return groups;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值