变位词(anagrams):指的是组成两个单词的字符相同,但位置不同的单词。比如说,abbcd和abcdb就是一对变位词。在介绍问题c之前,我们先看看如何判断两个字符串是否是变位词。
分析:求解题目C有两种思路:
【思路一】
由于变位词只是字母的顺序改变,字符长度,字符种类没有改变,所以根据此我们只要重新根据字典序排序一下,两个字符串也就一样了。如abcbd和acdbb是一对变位词,按照字典序排序之后他们都变成了abbcd。这种方法的时间效率根据你使用的排序算法不同而不同,基于比较的排序的时间复杂度下界为O(nlogn),两字符串按位比较的复杂度为O(n)。
#include <stdio.h> #include <stdlib.h> #include <string.h> int cmpfunc( const void *a , const void *b ){ return *(char *)a - *(char *)b;//升序排序 //return *(char *)b - *(char *)a; //降序排序 } void anagrams(char * s1,char *s2){ int len1 = strlen(s1); printf("length of s1 : %d ",len1); int len2 = strlen(s2); printf("length of s1 : %d ",len1); //注意短路运算,优先顺序从左到右 if(len1 != len2 || len1==0 || len2 ==0){ printf("they are not anagrams "); return; } qsort(s1,len1, sizeof(char), cmpfunc); qsort(s2,len2, sizeof(char), cmpfunc); /*测试代码 int i; for(i=0;s1[i]!=' ';i++){ printf("%c ",s1[i]); } printf(" "); for(i=0;s2[i]!=' ';i++){ printf("%c ",s2[i]); } printf(" "); */ if(strcmp(s1,s2)==0){ //strcmp的返回值正,0,负 printf("they are anagrams "); }else{ printf("they are not anagrams "); } } int main(int argc, char* argv[]){ char s1[] = "abbcb!de?"; char s2[] = "ac?edbbb!"; anagrams(s1,s2); return 0; }
注意,本代码使用了库函数qsort,需要自己定义比较函数cmpfun,我们这里使用常规的比较函数,基于ASCII码值的比较。并且排序之后字符串的比较我们使用了标准函数strcmp,是区分字符串大小写的。如果想忽略大小写,需要使用自定义的strcmp。
【思路二】
由于组成变位词的字符是一模一样的,数目也一样,因此我们可以先统计每个字符串中各个字符出现的次数, 然后看这两个字符串中各字符出现次数是否一样。如果是,则它们是一对变位词。
这需要开一个辅助数组来保存各字符的出现次数。我们可以开一个大小是26的整数数组用于记录字符串中每个字符(不区分大小写的话,最多26个英文字母)出现的次数。遍历第一个字符串时,将相应字符出现的次数加1;遍历第二个字符串时, 将相应字符出现的次数减1。最后如果数组中所有元素值都为0,说明两个字符串是一对变位词。 (第1个字符串中出现的字符都被第2个字符串出现的字符抵消了),如果数组中有一个不为0,说明它们不是一对变位词。
代码一:
#include <stdio.h> #include <string.h> void anagrams(char * s1,char *s2){ int i,count[26]; memset(count,0,sizeof(count)); int len1 = strlen(s1); int len2 = strlen(s2); //注意短路运算,优先顺序从左到右 if(len1 != len2 || len1==0 || len2 ==0){ printf("they are not anagrams "); return; } for(i=0;s1[i]!='