字母异位词(anagram)的不同复杂度实现

来源:互联网 发布:淘宝助理怎么打印订单 编辑:程序博客网 时间:2024/05/20 13:10

题目
这是一道微软的面试题,题目是这样的:两个单词如果包含相同的字母,次序不同,则称为字母易位词(anagram)。例如,“silent”和“listen”是字母易位词,而“apple”和“aplee”不是易位词。请定义函数检查两个单词是否是字母易位词。可以假设两个单词字母均为小写。要求算法复杂度尽量低。
看到这个题目,你的第一想法是怎么做?
思路一
首先,最基本的思路,便是检测字符串s1中的字符是否都出现在s2中(在s1和s2长度一样的前提下)。为了解决“apple”和“aplee”不是易位词的这种情况,不能仅仅判断出现在s2中就可以了,还需要做个标记。将s2中已经和s1对应上的位置标记为0,C++实现如下:

bool anagramSolution1(string s1,string s2){    if(s1.size()!=s2.size())        return false;    bool stillOk=true;    for(int i=0;i<s1.size()&&stillOk;i++)    {        bool found=false;        for(int j=0;j<s2.size()&&!found;j++)        {            if(s2[j]==s1[i])            {                s2[j]=0;                found=true;            }        }        if(found)        {            stillOk=true;        }        else        {            stillOk=false;        }    }    return stillOk;} 

让我们考虑一下算法复杂度,对于s2中的每个元素,s1都会从头开始遍历一遍,所以算法的复杂度为O(n^2)。
可以想一想,有没有算法复杂度比这个更低的呢?
思路二
通过题目,我们可以想到,字母易位词即为各个字母的数目相同,而顺序不一致。因而,如果对字符串按照字母顺序排序后,那么两个字符串应该完全一致。这样算法复杂度是否更低?
C++实现如下:

bool anagramSolution2(string s1,string s2){    if(s1.size()!=s2.size())    return false;    sort(s1.begin(),s1.end());    sort(s2.begin(),s2.end());    return s1==s2;}

这个复杂度是多少呢,因为其中用到了排序算法(头文件包含algorithm)和s1、s2比较的算法。所以复杂度为O(n*logn)。比思路一的复杂度降低了。
思路三
思路二利用了字母易位词即为各个字母的数目相同,而顺序不一致。我们从另外一个角度思考,字母一共有多少个?很明显,只有26个(只考虑小写字母)。那么,我们可以为字符串s1和s2分别设置26个计数器,然后判断这对应位置的计数是否相等,如果对应计数完全相等,则为字母易位词。
C++实现如下:

bool anagramSolution3(string s1,string s2){    if(s1.size()!=s2.size())    return false;    int count1[26]={0};    int count2[26]={0};    for(int i=0;i<s1.size();i++)    {        count1[s1[i]-'a']+=1;    }    for(int j=0;j<s2.size();j++)    {        count2[s2[j]-'a']+=1;    }    bool match=true;    for(int idx=0;idx<26&&match;idx++)    {        if(count1[idx]!=count2[idx])        {            match=false;        }    }    return match;}

算法的复杂度为O(n+n+26),即为O(n),为线性复杂度的算法。

阅读全文
0 0
原创粉丝点击