问题描述
实现一个函数,可以左旋字符串中的k个字符。例如 ABCD左旋一个字符得到BCDA ,ABCD左旋两个字符得到CDAB
解法一:暴力移位法
- 假设将ABCDE左旋转一个字符得到的是BCDEA
- 首先将A储存起来
- 找到’\0’循环结束,避免将’\0’移动
- 然后BCDE逐个向左移动
参考代码:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
void left_swap(char *str, int n)
{
assert(str != NULL);
while (n--)
{
char *cur = str;
char temp = *cur;
//将第一个元素储存在temp中
while (*(cur + 1) != '\0')
{
*cur = *(cur + 1);
//逐个左移
cur++;
}
*cur = temp;
//将之前储存起来的元素放在最后
}
}
int main()
{
char arr[] = "ABCDE";
int num = 0;
printf("请输入要旋转的个数:");
scanf_s("%d", &num);
left_swap(arr, num);
printf("%s\n", arr);
system("pause");
return 0;
}
解法二:三步翻转法
- 假设将ABCDE左旋转两个字符得到的是CDEAB
- 首先翻转要旋转的字符ABCDE——>BACDE
- 然后翻转不旋转的字符BACDE——>BAEDC
- 最后翻转整个字符串BAEDC——>CDEAB
参考代码:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
static void reverse(char *left, char *right)
{
assert(left != NULL);
assert(right != NULL);
while (left < right)
{
char temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}//逆置字符串
void left_swap(char *str, int n)
{
reverse(str, str + n - 1);
reverse(str+n, str+strlen(str)-1);
reverse(str, str + strlen(str) - 1);
//传入三步的首位地址
}
int main()
{
char arr[] = "ABCDE";
int num = 0;
printf("请输入要旋转的个数:");
scanf_s("%d", &num);
left_swap(arr, num);
printf("%s\n", arr);
system("pause");
return 0;
}
推广:判断一个字符串是不是经过另一个字符串旋转的到的
- 假设判断BACDE是不是字符串ABCDE旋转得到的
- 首先,拼接字符串ABCDE自身得到字符串ABCDEABCDE
- 可以发现如果BACDE是字符串ABCDE旋转得到的,就一定是字符串ABCDEABCDE的子串
- 由库函数strstr判断BACDE是不是字符串ABCDEABCDE的子串
参考代码:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>
int is_swap(char *sour, const char* cmp)
{
assert(sour != NULL);
assert(cmp != NULL);
strncat(sour, sour, strlen(sour));
//拼接自身字符串
if (strstr(sour, cmp) != NULL)//判断是否为子串
{
return 1;
}
return 0;
//返回1表示是,返回0表示不是
}
int main()
{
char sour[20] = "ABCDEF";
char *cmp = "CDEFAB";
int ret=is_swap(sour, cmp);
if (1 == ret)
{
printf("是\n");
}
else
{
printf("不是\n");
}
system("pause");
return 0;
}
在上边的代码连接字符串用了
strncat
函数,为什么不用strcat
函数呢?
strcat(str,str)
会引起死循环,因为strcat
函数要先找到第一个字符串的’\0’,找到之后从’\0’开始追加字符串,把第一个字符拷贝过去之后’\0’已经被覆盖了,所以会引起死循环。