目录
题述:
左旋字符串中的k个字符
例子:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
法一、暴力左旋
思路:
左旋几个字符就旋转几次
- 1.每次旋转一个字符
- 2.后面的len-1个字符往前移动(向左)
- 3.tmp放在字符串末尾,则完成左旋
代码实现
#include<stdio.h>
#include<string.h>
void left_rotate(char* str, int k)//用字符指针接收
{
int i = 0;
int len = strlen(str);//求出数组长度
for (i = 0; i < k; i++)
{ //每循环一次就会换一个字符,所以换几个字符循环几次
//1.每次旋转一个字符
char tmp = *str;
//2.后面的len-1个字符往前移动(向左)
int j = 0;
for (j = 0; j < len - 1; j++)
{//最后结束的标志是arr[len-2] = arr[len-1]
*(str + j) = *(str + j + 1);
//arr[j]=*(arr+j)等价于*(str+j),所以arr[j]=arr[j+1],只不过函数内部没有arr所以要用str表示
//前一个元素值等于后一个元素值,实现左旋一位
}
//3.tmp放在字符串末尾,则完成左旋
*(str + len - 1) = tmp;
}
}
int main()
{
char arr[10] = "ABCDEF";//设置一个字符数组
int k = 0;//k是需要左旋的字符个数
scanf("%d", &k);
left_rotate(arr,k);//传入首元素地址和需要左旋字符个数
printf("%s\n", arr);
return 0;
}
法二、字符串逆转法
思路:
故只需写个交换字符串的函数,多次调用即可完成左旋字符串
代码实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
void reverse(char* left, char* right)
{
assert(left);
assert(right);//传入函数的不是空指针程序才能正常运行
while (left < right)
{
char temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}
void left_rotate(char* str, int k)
{
int len = strlen(str);
if (k > len)
{
k %= len;//防止因为k大于字符串长度导致的出错
}
reverse(str, str + k - 1);//需要左旋的字符逆序
reverse(str + k, str + len - 1);//除左旋外剩余的字符逆序
reverse(str, str + len - 1);//整个字符串再逆序
}
int main()
{
char arr[10] = "ABCDEF";
int k = 0;
scanf("%d", &k);
left_rotate(arr, k);
printf("%s\n", arr);
return 0;
}
为什么法二需要k>len时k%=len呢?
k>len对于法二,其是建立在字符串逆转的基础上,若k>len,那就会造成数组越界,因为字符串逆序要传入地址,但你用了越界的地址就非法访问了。
但法一只是循环k次,他不会造成数组越界,如果k>len,顶多多左旋k-len个字符罢了,完全符合题意的。