在《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/