此前不太熟悉这种类型的题目,特此做一个合计的方法总结。 包括字符串中字符的左旋(右旋),和判断一个字符串是否是由另一个字符串旋转(左旋或者右旋)而来。
一.字符串的左旋(右旋)
由于左旋和右旋思路一致,这里仅介绍左旋方法。 这种题目有两种思路: 1.首字符的后置以及其余元素的往前推置,循环重复此过程K次(k为左旋字符个数)。
eg: 字符串为“ABCDEF\0”,要旋转2个字符, 首先保存首字符到一个变量,然后把其余变量全部提前一位置放,即为“BCDEF \0”(此处注意,最后的终止符\0不要提前,留出一个空位) 再把用来保存的变量给字符串最后一个位置(除\0外),即为“BCDEFA\0” 再做一次此过程即为“CDEFGA \0”——》“CDEFGAB\0”
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Exchange(char *str, int k)
{
int i,m;
char temp;
char *sta;
for (i = 0; i < k; i++)
{
sta = str;
temp = *str;//保存首字符
for (m = 0; m <= (int)strlen(str)-1; m++)//元素提前放置
{
*sta = *(sta + 1);
sta++;
}
*(str+strlen(str)) = temp;//将首字符放置最后
}
}
int main()
{
int leng;
printf("请输入要左旋几个字符\n");
scanf("%d", &leng);
char str[] = "ABCDEFG";
Exchange(str,leng);
printf("%s\n", str);
system("pause");
return 0;
}
2.三步旋转法 这种方法是由观察得来,旋转后的字符串有此规律: 旋转前“ABCDEFG” 旋转后“CDEFGAB” 将旋转后的字符逆置得 “CDEFGBA” 将未旋转的字符逆置得 “GFEDCBA” 再将全部字符逆置就得到了原来的字符串“ABCDEFG” 原字符串旋转时反向操作即可
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void reverse(char *left, char *right)//逆置函数
{
char temp;
while (left < right)
{
temp = *left;
*left = *right;
*right = temp;
left++; right--;
}
}
void Exchange(char *str, int leng)//三步逆置
{
reverse(str, str + leng-1);
reverse(str + leng, str+strlen(str)-1);
reverse(str, str + strlen(str) - 1);
}
int main()
{
int leng;
printf("请输入要左旋几个字符\n");
scanf("%d", &leng);
char str[] = "ABCDEFG";
Exchange(str,leng);
printf("%s\n", str);
system("pause");
return 0;
}
二.判断一个字符串是否是由另一个字符串旋转而来 1.第一种思路是不借助字符串库函数,将需要判断的字符串按照三步逆置法判断是否和原字符串相同,但是这种方法效率较差,而且时间复杂度高。
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void reverse(char *left,char *right)
{
char temp;
while (left < right)
{
temp = *left;
*left = *right;
*right = temp;
left++; right--;
}
}
int judgeStr(char str1[],char str2[],char str3[])
{
int i,m=0,sum=0,s;
char *sta ;
char *fina ;
int length = strlen(str1);
for (i = 0; i <(int)strlen(str2); i++)
{
str3[i] = str2[i];
}
for (i = 0; i <= (int)strlen(str1) - 1; i++)
{
sta = str3;
fina = str3 + strlen(str1) - 1;
reverse(sta, sta + i);
reverse(sta + i + 1, fina);
reverse(sta, fina);
for (; m < (int)strlen(str1); m++)
{
if (str1[m] != str3[m])
{
sum++;
break;
}
}
for (s = 0; s<(int)strlen(str2); s++)
{
str3[s] = str2[s];
}
if (sum == 4)
{
return 0;
}
}
return 1;
}
int main(void)
{
char str1[] = "ABCDE";
char str2[] = "BCDEA";
char str3[] = "BACDE";
char stra[] = "AAAAA";
int judge;
judge = judgeStr(str1, str2,stra);
if (judge == 1)
{
printf("str2是由str1旋转得来的\n");
}
else
{
printf("str2不是由str1旋转得来的\n");
}
judge = judgeStr(str1, str3,stra);
if (judge == 1)
{
printf("str3是由str1旋转得来的\n");
}
else
{
printf("str3不是由str1旋转得来的\n");
}
system("pause");
return 0;
}
2.使用字符串库函数解决 使用此方法需要注意到一个规律: 一个字符串后面再接一个和自身相同的字符串后,此字符串中就出现了所有旋转可以得到的结果。
eg: A B C D A B C D,其中有所有的“ABCD”旋转结果,BCDA(2~5),CDAB(3~6),DABC(4~7)。
所以做法就是利用库函数将原字符串拼接一个自身,再在字符串中查找需要判断的字符串即可。
源代码:
#include<stdio.h>
#include<string.h>
int judge(char *str1, char *str2)
{
strncat(str1, str1, strlen(str1));//原字符串拼接本身
char *result = strstr(str3, str2);//查找目标字符串
if (result == NULL)
{
return -1;
}
else
{
return 0;
}
}
int main()
{
char str1[] = "ABCDE";
char str2[] = "CDEAB";
char str3[] = "DEBAC";
int result = judge(str1, str2);
if (result == -1)
{
printf("str2不是由str1旋转得到\n");
}
else
{
printf("str2是由str1旋转得到\n");
}
result = judge(str1, str3);
if (result == -1)
{
printf("str3不是由str1旋转得到\n");
}
else
{
printf("str3是由str1旋转得到\n");
}
system("pause");
return 0;
}