题目:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
方法一:
我们画个图分析一下:
基本逻辑:
就是我们每一次旋转之前,我们就取出 arr 数组的首元素存放在 tmp 中,然后将 arr 数组剩余的每一个元素都往前移动一位,最后我们再把 tmp 中的元素放回 arr 数组末尾的位置。
实现算法:
我们发现,abcd 4个字符旋转 k = 4 个字符时,数组就回到了本身数组 abcd 。这时,我们可以这样理解,虽然我们旋转了4个字符,但我们实际上我们旋转了0个字符;依次类推,旋转5个字符,实际上旋转了1个字符;接下去也是如此......接下来,我们再把字符长度加长,变成abcde 5个字符,旋转 k = 5 个字符时,数组就回到了本身数组 abcde,后面的分析就跟4个字符分析是一样的。然后,我们能够得到这样一个表达式 num(实际次数) = k % len(数组字符个数)。
代码实现:
#include <stdio.h>
#include <string.h>
void Turn_left(char arr[],int k)
{
int len = strlen(arr);
//求得真实的旋转次数
int num = k % len;
for (int i = 0; i < num; i++)
{
//每次移动一个
char tmp = arr[0];
int j = 0;
for (j = 0; j < len - 1; j++)
{
//移动数据
arr[j] = arr[j + 1];
}
arr[j] = tmp;
}
}
int main()
{
char arr[] = "abcd";
int k = 0;
scanf("%d", &k);//输入旋转字符个数
Turn_left(arr, k);
printf("%s\n", arr);
return 0;
}
运行结果:
方法二:
我们也可以画个图分析一下:
这里我们要用到两个函数:
strcpy() //字符串拷贝
strcpy(str1,str2)//将str2的元素拷贝到str2中
strncat()//这也是字符串拷贝
strncat(tmp,arr,k)//把arr开始的元素 拷贝到tmp这个字符串的后面,拷贝k个
代码实现:
#include <stdio.h>
#include <string.h>
void Turn_left(char arr[], int k)
{
int len = strlen(arr);
int num = k % len;
char tmp[1000] = { 0 };
//从arr + num的位置 开始拷贝字符串到tmp里面
strcpy(tmp, arr + num);
//把arr开始的元素 拷贝到tmp这个字符串的后面,拷贝num个
strncat(tmp, arr, num);
//最后将tmp整个数组元素复制到arr数组中
strcpy(arr, tmp);
}
int main()
{
char arr[] = "abcd";
int k = 0;
scanf("%d", &k);//输入旋转字符个数
Turn_left(arr, k);//2
printf("%s\n", arr);
return 0;
}
运行结果:
方法三:
最后一种方式我们也画图分析一下:
代码实现:
#include <stdio.h>
void Reverse(char arr[], int i, int j)
{
while (i < j)
{
char tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
}
void Turn_left(char arr[], int k)
{
int len = strlen(arr);
int num = k % len;
//将num位置前面的元素逆序
Reverse(arr, 0, num - 1);
//将num位置以及之后的元素逆序
Reverse(arr, num, len - 1);
//整个数组逆序
Reverse(arr, 0, len - 1);
}
int main()
{
char arr[] = "abcd";
int k = 0;
scanf("%d", &k);//输入旋转字符个数
Turn_left(arr, k);//2
printf("%s\n", arr);
return 0;
}
运行结果: