题目:实现一个函数,可以左旋字符串中的k个字符。
比如:ABCD左旋一个字符得到BCDA
方法一:
可以定义一个temp变量临时保存第一个字符,然后从第二个元素开始,依次往前移动,最后将第一个字符放到最后就好了,要左旋多少个就把之前步骤重复多少次
- 注意:如果左旋次数多的话,有些中间的结果会和最终结果一样,所以求出有效左旋次数会优化些
代码如下:
void LeftMove(char *str, int len,int num)
{
assert(str);
assert(len>0);
assert(num);
num %= len;//有效次数
while (num--)//左旋次数
{
//左旋一次的步骤
int i = 0;
char temp = *str;//放第一个字符
for (; i < len - 1; i++)
{
str[i] = str[i + 1];//指针可以下标引用式访问
}
str[i] = temp;//注意临界
}
}
int main()
{
int num = 0;
char str[] = "ABCD";//要改字符串,所以这里不能用char *str=...
int len = strlen(str);//有效元素个数,不包括'\0'
printf("before:%s\n", str);
printf("请问你需要左旋几个字符\n");
scanf("%d", &num);
LeftMove(str, len, num);
printf("after:%s\n", str);
system("pause");
return 0;
}
方法二:
上面的方法用了两个循环,时间复杂度为O(n^2),可以再优化一下:要左旋几次,就把前面几个作为一个整体,后面为一个整体,两部分分别逆置,最后再总体逆置就好啦,就是不太好想
函数实现部分:
//逆置
void reserve(char* start, char* end)
{
while (start<end)
{
*start ^= *end;
*end ^= *start;
*start ^= *end;
start++;
end--;
}
}
//左旋
void LeftMove1(char *str, int len, int num)
{
assert(str);
assert(len>0);
assert(num);
num %= len;//有效次数
char *mid = str + num - 1;
reserve(str, mid);//逆置前面
reserve(mid + 1, str + len - 1);//逆置后面
reserve(str, str + len - 1);//逆置整体
}
方法三:
可以把两个相同的字符串拼在一起,然后要左旋几次就从哪里开始向后拿一个字符串的长度
函数实现部分:
void LeftMove2(char* str, int len, int num)
{
assert(str);
assert(len > 0);
assert(num);
num %= len;
char *buf = (char*)malloc(2 * len + 1);//申请放两个字符串的空间
strcpy(buf, str);//把str拷到buf里
strcat(buf, str);//把str拼接到buf里得到双倍串
//左旋
strncpy(str, buf + num, len);//
free(buf);// (在堆上开辟的空间,自己释放)
buf = NULL;
}