【c语言】练习:判断两个字符是否为旋转字符

在《Cracking the coding interview》一书,有一道判断两个字符串是否为旋转字符的题目。

    假设给出两个字符串s1,s2和一个isSubstring函数,isSubstring函数能够检测一个字符串是不是另一个字符串的子串。 请结合isSubstring函数实现以下功能,只使用一次isSubstring,判断s2是不是s1的旋转字符串。(旋转字符串:"waterbottle"是"erbottlewat"的旋转字符串。)

 

我的思路:

        先判断两个字符串是否是变位词,变位词:“abc”是“cba”或“bca”等的变位词。

        如果是变位词,找到s1第一个单词在s2中的位置p1,判断从p1到s2末尾的字符串是否等于s1从行首到某个位置p3的字符串。

        若相等,使用isSubstring判断s1中从p3到末尾的字符串是否是s2的一个子串。

        若成立,则说明s2是s1的旋转字符串。中间仅仅使用一次subString函数。

代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>



#define MAX 256



typedef enum logic{False=0,True} BOOL;



BOOL isShift(const char *str1,const char *str2){

        int  tmp[MAX]={0};

        int i;

        int curl;



        char *p1str=(char *)str1;

        char *p2str=(char *)str2;



        if(strlen(str1) != strlen(str2))

                return False;

        if(NULL == str1 || NULL == str2 )

                return False;





        while('\0' != *p1str ){

                curl=(int)(*p1str);

                tmp[curl]++;

                p1str++;

        }

        while('\0' != *p2str ){

                curl=(int)(*p2str);

                tmp[curl]--;

                p2str++;

        }



        for(i=0;i<MAX;i++){

                if(0 != tmp[i])

                        return False;

        }

        return True;



}



BOOL isRotate(const char* str1, const char * str2){

        char *p2,*p3;

           char *p4=(char *)str2;



        if(True == isShift(str1,str2))

        {

                while(*p4!='\0'){

                        if(*str1 == *p4)

                        {

                                p2=(char *)p4;

                                p3=(char *)str1;

                                while(*p2!='\0'){

                                        if(*p2==*p3)

                                        {

                                                p2++;

                                                p3++;

                                        }

                                        else break;

                                }

                                if(*p2=='\0') break;



                        }

                        p4++;

                }



                if( NULL == strstr(str2,p3) ) return  False;

                else  return True;

        }

        else

                return False;



}



int main(){



        char s1[]="apple";

        char s2[]="pleap";



        char s3[]="elppa";

        char s4[]="eappa";

        if( False == isRotate(s1,s2)) printf("no, s1  not the rotation of s2\n");

        else printf("yes, s1 rotation of s2\n");



        if( False == isRotate(s2,s3)) printf("no, s2  not the rotation of s3\n");

        else printf("yes, s3 rotation of s2\n");



        if( False == isRotate(s1,s4)) printf("no, s1  not the rotation of s4\n");

        else printf("yes, s1 rotation of s4\n");



        return 0;

}

       

很快写出了代码,但运行结果却是错误的,使用gdb不断地调bug,语法和逻辑没有破绽,运行却总是出错,找了很久,直到最后才发现,错在一个小地方(代码中红色字段),把strstr函数的参数写反了,所以strstr函数一直返回NULL。发生这种错误,真是让人无法接收。

 

又在《编程之美》上看到一个相似的例题,其中提出一种非常简洁的方法:

它的思路:

      假设两个字符串分别为ABCD和DCBA,将第一个字符串“ABCD”连接成新的字符串“ABCDABCD”。

      比较新的字符串"ABCDABCD“与字符串”DCBA“,判断字符串”DCBA“是不是另一个字符串的子串。

      如果是,则说明是旋转字符串。

(思路之简洁巧妙,让人赞叹。相比之下,我的方法十分笨拙,而且容易出错,想来也对,代码越长越可能出错,只有这种时候,才能深刻地体会到算法的重要性,“简单”的重要性)

 最后,向大家推荐一个非常棒的个人网站,网站作者解决了cracking the coding interview一书的所有题目,很厉害的一个家伙。

网站地址:http://hawstein.com/

你可能感兴趣的:(C语言)