C语言:3种方法实现左旋字符串

题目:实现一个函数,可以左旋字符串中的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;
}
发布了73 篇原创文章 · 获赞 2 · 访问量 2871

猜你喜欢

转载自blog.csdn.net/weixin_43219708/article/details/103348579