题述
给定两个字符串S1和S2,要求判断S2能否被S1做循环移位得到的字符串包含。
例如:s1=AABCD和S2=CDAA,返回true, s1=ABCD和s2=ACBD,返回false。
例如:s1=AABCD和S2=CDAA,返回true, s1=ABCD和s2=ACBD,返回false。
手写代码
思路我倒是一眼就看穿了:将s1接在s1后面,形成两个s1,直接判断s2是否存在于2个s1之中即可解决s1是循环位移的问题
不过这个手写的代码部分真的就是惨不忍睹了。如下图所示:
运行代码
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int isContain(char *s1,char *s2){
char *temps1,*temps11;
temps1=malloc(1);//必须要调用一次分配内存的函数,分配的大小却无所谓,这是我没想到的
temps11=malloc(strlen(s1)+1);
strcpy(temps1,s1);
strcpy(temps11,s1);
strcat(temps1,temps11);
char *i,*j;
i=temps1;
j=s2;
for(;*i!='\0';i++){ //这个地方必须是加了*号,表示取一个字符,而如果只是i的话表示的是一个字符串
if(*j=='\0') break;
if(*i==*j){
j++;
}else{
j=s2;
}
}
if(*j=='\0') {
return 1;
}else{
return 0;
}
}
int main(){
int result=isContain("AABCD","CDAA");
printf("%d\n",result);
}
运行结果:
1
减少冗余代码
也发现了一些技巧,调用strcat的使用不一定需要两个字符串,对同一个字符串也能做这样的事
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int isContain( char *s1, char *s2){
char *i,*j;//应该不能再少了吧?如果直接拿着s1和s2移动指针,原字符串都破坏了
i=malloc(1);//最好不要这样写,因为i所需要的空间明显不是1,这样把指针后面的内存空间给覆盖掉
strcpy(i,s1);//i指向s1
strcat(i,i);//s1后面再加一个s1
j=s2;//j指向s2
for(;*i!='\0';i++){
if(*j=='\0') return 1;
if(*i==*j){
j++;
}else{
j=s2;
}
}
return 0;
}
int main(){
int result=isContain("AABCD","CDAA");
printf("%d\n",result);
}
运行结果是
1
节省空间的办法
上述方法利用了“提高空间复杂度来降低时间复杂度的办法”思路,适用于对时间复杂度要求高的场合,我们能否更进一步,不需要申请过多的空间,而同样解决这个问题。
#include <stdio.h>
int isContain(char *s1, char *s2){
char flag=0;//标记对s1的遍历
char *i,*j;
i=s1;
j=s2;//j指向s2
for(;;){
if(*i=='\0'&&flag == 1){ //第二次达到s1字符串末端
break;
}
if(*i=='\0'){ //如果i第一遍遍历到了最后一个,我就让其回到原位
i=s1;
flag=1; //并且用一个标记,其已经到过一次末尾了
continue;
}
if(*j=='\0') return 1;
if(*i==*j){
++j;
}else{
j=s2;
}
++i; //让指向s1的字符串指向下一个
}
return 0;
}
int main(){
int result=isContain("AABCD","CDAA");
printf("%d\n",result);
}