题目名称:
字符串左旋
题目内容:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
方法一:暴力求解
这种方法相对比较容易,我们先来看看代码:
void left_move(char* arr, int k)
{
int i = 0;
assert(arr);
int len = strlen(arr);
for (i = 0; i < k; i++)
{
//左旋转1个字符
//1. 保存第一个字符
char tmp = *arr;
//2. 把后续的字符一次往前移动
int j = 0;
for (j = 0; j < len - 1; j++)
{
*(arr + j) = *(arr + j + 1);
}
//3. 把保存好的第一个字符存放在最后
*(arr + len - 1) = tmp;
}
int main()
{
char arr[] = "abcdef";
//左旋转字符串
left_move(arr, 1);
printf("%s\n", arr);//打印字符串
return 0;
}
首先我们建立数组来存储abcdef,此处不能用char* p的指针存储“abcdef”中a的地址,因为用指针存储,存放的是常量字符串,而常量字符串是不可被修改的。不可被修改就没有旋转字符串做法一说。
这时自定义函数left_move来实现字符串的左旋,将数组的数组名与需要左旋转的次数做为实参传入该函数中。
left_move函数内部分析:假设我们只让字符串左旋一次,要用for循环来实现。而左旋的思路为:首先将字符串的首字母存入临时变量中,再将首字母后的所有字母提前1位(除了’\0’以外),再将临时变量中首字母的内容存放到字符串的最右边。以下示意图可以更容易理解。
方法二:分开逆转字符串
思路:假设我们需要左旋转前两个字母,因此我们先让前两个字母进行逆转;再将除了前两个字母以外的所有字母也逆转;最后再将所有字母进行逆转,结果我们会发现这样的方法直接将前两个字母达成了左旋转效果。下面的图能够帮助理解。
先将前两个字母逆转:
将除了前两个字母进行逆转:
将所有字母逆转:
代码如下:
void reverse1(char* l, char* r)
{
assert(l && r);//避免l与r指针是空指针
while (l < r)//进行字母逆转
{
char tmp = *l;
*l = *r;
*r = tmp;
r--;
l++;
}
}
void reverse(char* arr1, int len, int k)
{
assert(arr1);
k %= len;//避免需要左旋的字母过多
reverse1(arr1, arr1 + k - 1);//先将需要左旋的字母逆转
reverse1(arr1 + k, arr1 + len - 1);//除了需要左旋的字母以外的字母逆转
reverse1(arr1, arr1 + len - 1);//所有字母逆转
}
int main()
{
char arr1[] = "ABCDE";
int len = strlen(arr1);
int k = 2;//假设左旋转前两个字母
reverse(arr1, len, k);
printf("%s\n", arr1);
return 0;
}
题目名称:
字符串旋转结果
题目内容:
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC
方法一:
思路:在上面题型中,我们得知了字符串左旋的两种方法。这题我们关键就在于如何判断一个字符串是否是另一个字符串左旋得来的。比较两个字符串是否相等,这里我们联想到了strcmp函数,如果两个字符串相等,strcmp函数会返回0。当然,如果两个字符串的长度都不相等,那么两个字符串如何左旋转也不可能相等。
代码如下:
#include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char* left, char* right)
{
while (left < right)
{
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
void left_move(char* arr1,int k)
{
int len = strlen(arr1);
reverse(arr1, arr1 + k-1);
reverse(arr1 + k, arr1 + len - 1);
reverse(arr1, arr1 + len - 1);
}
int is_left_move(char* arr1,char* arr2)
{
int len1 = strlen(arr1);
int i = 0;
for (i = 0; i < len1 - 1; i++)
{
left_move(arr1,1);
if (strcmp(arr1, arr2) == 0)
{
return 1;
}
}
return 0;
}
int main()
{
char arr1[20] = "AABCD";
//AABCDAABCD
char arr2[] = "BCD";
int ret = is_left_move(arr1, arr2);
if (ret == 1)
printf("YES\n");
else
printf("NO\n");
return 0;
}
方法二:
思路:利用库函数strncat(在所需要追加的字符串后面追加字符),在形参中我们可见第一个传入的实参是所需要追加字符的地址,第二个传入的是追加的字符串的来源,第三个传入的是追加字符的个数。而strstr函数是观察一个字符串从首地址开始往后数是否能遇到另一个字符串。例如字符串1 abcdefg与字符串2 def,从字符串1的首元素a的地址往后数,在d地址处开始到f地址,正好与字符串2的def字符串相等,则strstr会返回d的地址,如果需要打印,则能打印出字符串defg。以下是strncat函数与strstr函数的形式参数及作用。
代码如下:
int is_left_move(char arr1[], char arr2[])
{
assert(arr1);
assert(arr2);
int len1 = strlen(arr1);
int len2 = strlen(arr2);
if (len1 != len2)
return 0;
//1. 给arr1的后边追加一个arr1中的字符串
strncat(arr1, arr1, len1);
//2. 判断arr2是否是arr1的字串
if (NULL == strstr(arr1, arr2))//如果arr1的内容没有arr2的内容,则返回NULL
{
return 0;
}
else
{
return 1;
}
int main()
{
char arr1[20] = "AABCD";
//AABCDAABCD
char arr2[] = "BCD";
int ret = is_left_move(arr1, arr2);
if (ret == 1)
printf("YES\n");
else
printf("NO\n");
return 0;
}
如果这篇文章对您理解字符串旋转问题有帮助,麻烦点个赞谢谢!