01_02字符串包含

来源:互联网 发布:网络推广方式的优缺点 编辑:程序博客网 时间:2024/06/10 19:56

概括

这个还是在github上的开源项目,程序员编程艺术.今天开始第二小节的阅读及编写代码.
题目
给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短。请问,如何最快地判断字符串B中所有字母是否都在字符串A里?

为了简单起见,我们规定输入的字符串只包含大写英文字母,请实现函数bool StringContains(string &A, string &B)

比如,如果是下面两个字符串:

String 1:ABCD

String 2:BAD

答案是true,即String2里的字母在String1里也都有,或者说String2是String1的真子集。

如果是下面两个字符串:

String 1:ABCD

String 2:BCE

答案是false,因为字符串String2里的E字母不在字符串String1里。

同时,如果string1:ABCD,string 2:AA,同样返回true。
分析
简单来说就是如果字符串B所有的字母,在字符串A中都能找到就返回true,否则就返回false.

思路一
看到这道题目我首先想到就是利用C语言中的库函数strchr,
这个函数的接口形式是:
char* strchr(const char *s,int c)
参数s是一个常量字符串,c代表一个字符,就是判断c是否存在于s,如果存在就返回第一次指向c的指针.否则返回NULL;
知道这个函数我们就能很快写出这道题了.

bool StringContains(char *A, char* B){    for(int i=0;i<strlen(B);i++)    {        if(strchr(A,B[i]) ==NULL )        {            return false;        }    }    return true;}int main(){    char str1[80];                            char str2[80];                            cin>>str1;                                cin>>str2;                                cout<<StringContains(str1,str2)<<endl;}

总结
但反思,这种解法够快吗?我们不知道strchr具体的内部实现,假设它是用最优的解法,每次操作的时间复杂度也是O(n),所以总的时间复杂度是O(m*n),显然这不是一种好的解法.文章作者提供好几种思路给我们.有些还是很不错的,下面继续看看.

思路二
就是将两个字符先进行排序,然后分别对二个字符串进行轮询即可.

bool StringContain2(string &a,string &b){           //利用排序先进行排序    sort(a.begin(),a.end());    sort(b.begin(),b.end());    for(int i=0,j=0;i<b.size();i++)    {        while(b[i] > a[j])        {            j++;        }        if(j>a.size())            return false;    }    return  true;}

总结
这个方法相对于之前的方法还是改进了一点,排序时间复杂度是O(nlogn+mlogm),再加上轮询一遍是O(m+n),总的来说还是有不少的提升.
思路三
想了想题目的特殊要求,大写字母一共就26个,我们可以用stl中的set进行优化,由于set这种数据结构的互异性.这样字符串就把字符串中很多重复的元素去掉了.

bool StringContain3(string &a,string &b){           set<char> s1;    set<char> s2;    for(auto i:a)    {        s1.insert(i);    }    for(auto j:b)    {        s2.insert(j);    }    for(auto i:s2)    {        if(s1.find(i) != s1.end())        {            ;        }        else            return false;    }    return true;}

总结
利用set这个数据结构还是能优化不少的,set底层用的是红黑树实现的,保证插入和删除和查找的时间复杂度都是O(logn).所以总的时间复杂度是O(logn+logm+n*log26).
思路四
就是利用一个哈希进行存储.

bool StringContain4(string &a,string &b){    int Ha[26] = {0};    int Hb[26] = {0};    for(int i=0;i<a.size();i++)        Ha[a[i]-'A']++;    for(int i=0;i<b.size();i++)        Hb[b[i]-'A']++;    for(int i = 0;i < 26;i++)    {        cout<<Ha[i]<<" ";    }    cout<<endl;    for(int i = 0;i < 26;i++)    {        cout<<Hb[i]<<" ";    }    for(int i = 0;i<26;i++)    {        if(Ha[i] ==0 && Hb[i] != 0)            return false;    }    return true;}

总结
总的来说这种时间复杂的是最低的,额外的空间复杂度是O(m+n),时间复杂度是O(m+n).所以这种情况下是最优的.

0 0
原创粉丝点击