【C语言】左旋字符串解题思想

简介: 【C语言】左旋字符串解题思想

前言

🎈大家好,我是何小侠🎈

🍃大家可以叫我**小何或者小侠🍃**

💐希望能通过写博客加深自己对于学习内容的理解💐

🌸也能帮助更多人理解和学习🌸

欧阳修《浪淘沙·把酒祝东风》

欧阳修

把酒祝东风, 且共从容。 垂杨紫陌洛城东。 总 是当时携手处,游遍芳丛。

聚散苦匆匆,此恨无穷。今年花胜去年红。 可 惜明年花更好, 知与谁同?


    这篇博客我们一起来学习字符串左旋,这也是C语言中比较常见的题目,如果我们能学会今天的方法与思想,基本上你看到这种题目就不再感到棘手,如果说你本来就会那么不妨看看,说不定能让你的思路更加通畅。

    左旋字符串题目与思路🍊

    话不多说直接看题

    这就是我们的思路,将A字符放到字符串最后,然后让A之后的字符串都向前移动。

    再细节一点就是利用我们的老办法,创建临时变量当作中转站

    代码与细节🍊

    void left_rotate(char* arr, int k)
    {
      char* left = arr;
      int len = strlen(arr);
      char* right = arr + len - 1;
      while (k % len)
      {
        char tmp = *arr;
        left = arr;
        while (*left != *right)
        {
          *left = *(left + 1);
          left++;
        }
        *left = tmp;
        k--;
      }
    }
    int main()
    {
      char arr[] = "ABCD";
      int k = 0;
      scanf("%d", &k);
      left_rotate(arr, k);
      printf("%s", arr);
    }

    我们先要知道一个概念,可以优化我们的代码。

    如果我们要左旋4个的字符串就相当于我们不需要旋转,

    那么也就是说我们的旋转是有一个周期的,

    所以我们计算了strlen(arr)的长度,也就是字符的长度。

    那么如果我们需要左旋的数量是k的话,那么在我们left_rotate这个函数最外层while的循环次数也就是k% len。

    我们再来看代码,我用tmp作为临时变量永远存着数组第一个字符,

    不管字符左旋多少次,我们还是保存着第一个字符。

    然后我们*left = *(left + 1)利用这行代码来实现这个过程

    但是我们的left不能一直++,我们要在停在最后一个字符上面

    *left = tmp;利用这行代码完成这个过程

    最后我们的左旋次数减少一次就行

    最后也有一个细节,left 的位置还是在最后一个字符上面,所以我们用 left = arr;来让left在需要第二次左旋的时候,再指向第一个字符。

    巧解拼接法🍊

    我们直接看图

    如果我们直接在ABCD这个字符串后面追加一个ABCD,那么我们就可以得到所有的左旋可能,

    我们可以想一想,左旋实际上就是1,2,3,4这几种可能。即使推广到更长的字符串也是可以的。

    我们给出代码再来讲解

    void left_rotate(char* arr, int k)
    {
      int len = strlen(arr);
      k %= len;
      char tmp[5] = { 0 };
      strcpy(tmp, arr + k);//要逆序几个字符串也就是把arr+k放在逆序完的开头
      strncat(tmp, arr, k);
      strcpy(arr, tmp);
    }
    int main()
    {
      char arr[] = "ABCD";
      int k = 0;
      scanf("%d", &k);
      left_rotate(arr, k);
      printf("%s", arr);
    }

    我们创建一个与arr一样大的数组来接收逆序之后的字符串,当然也包括\0。

    strcpy(tmp, arr + k);
    我们来看这行代码,我们知道strcpy是字符串拷贝,那么也就是说从arr+k到\0,拷贝到tmp,我们用图来看看,假设我们的k是2。

    strncat(tmp, arr, k)

    再看这行代码,我们知道strncat是字符串追加,那么我们从什么地方开始追加,当然是从开头,为什么呢?我们现在只需要追加k个字符,为什么呢?因为我们需要左旋k个字符。
    我们看看图

    strcpy(arr, tmp);

    最后再把tmp拷贝到arr里面就行了,arr里最终得到的就是左旋后的字符串

    更巧妙的逆序法🍊

    我在上一篇博客已经介绍了逆序字符串的方法: link

    现在我们来看最后一种方法

    这种方法就更巧妙了,我们用了更长的字符串更好观察。

    void reverse(char* str1, char* str2)
    {
        char* left = str1;
        char* right = str2;
        while (left < right)
        {
            char tmp = 0;
            tmp = *left;
            *left = *right;
            *right = tmp;
            right--;
            left++;
        }
    }
    int main()
    {
      char arr[] = "ABCDEF";
      int k = 0;
      scanf("%d", &k);
        int len = strlen(arr);
        k %= len;
        reverse(arr, arr + k - 1);
        reverse(arr + k, arr + len - 1);
        reverse(arr, arr + len - 1);
      printf("%s", arr);
    }

    确实是一个很好用的方法,在我看来,我觉得还是逆序还是写起来比较舒服,而常规的左旋考虑的要多一点点。

    题目训练🍊

    我们可以利用拼接法

    int  left_rotate(char* arr1, char* arr2)
    {
      int len1 = strlen(arr1);
      int len2 = strlen(arr2);
      if (len1 != len2)
      {
        return 0;
      }
      char tmp[11] = { 0 };
      strcpy(tmp, arr1);
      strncat(tmp,arr2 , 5);
      return strstr(tmp, arr1)!=NULL;
      //  if (ret == NULL)
    //  {
    //    return 0;
    //  }
    //  else
    //  {
    //    return 1;
    //  }
    //}
    }
    int main()
    {
      char arr1[] = "AABCD";
      char arr2[] = "BCDAA";
      int ret = left_rotate(arr1,arr2);
      if (ret)
      {
        printf("YES\n");
      }
      else
      {
        printf("NO\n");
      }
      return 0;
    }
    

    首先判断两个字符串长度是否相等如果不相等就肯定不对

    然后还是拼接法的思路只不过多了一个strstr函数来判断是否为子串。

    还有就是这个返回值写的也比较简略是比较值得学习的。

    总结🍊

    这篇博客我介绍了C语言常见的问题——左旋字符串,但是左旋字符串并不代表一定就要左旋,我们也有很多的技巧来判断是否是左旋或者左旋后是怎么样的。

    最后如果这篇博客有帮助到你,欢迎点赞关注加收藏

    如果本文有任何错误或者有疑点欢迎在评论区评论


    目录
    相关文章
    |
    5月前
    |
    NoSQL 程序员 Redis
    C语言字符串的设计缺陷
    C语言字符串的设计缺陷
    53 1
    |
    1月前
    |
    C语言 C++
    【C语言】解决不同场景字符串问题:巧妙运用字符串函数
    【C语言】解决不同场景字符串问题:巧妙运用字符串函数
    |
    2月前
    |
    存储 C语言
    【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
    本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]=&quot;hello&quot;`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
    |
    2月前
    |
    存储 Serverless C语言
    【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数
    本文介绍了C语言中的`gets`和`puts`函数,`gets`用于从标准输入读取字符串直至换行符,并自动添加字符串结束标志`\0`。`puts`则用于向标准输出打印字符串并自动换行。此外,文章还详细讲解了`str`系列字符串操作函数,包括统计字符串长度的`strlen`、复制字符串的`strcpy`、比较字符串的`strcmp`以及拼接字符串的`strcat`。通过示例代码展示了这些函数的具体应用及注意事项。
    132 7
    |
    2月前
    |
    存储 人工智能 C语言
    C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
    本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
    |
    2月前
    |
    C语言
    C语言 字符串操作函数
    本文档详细介绍了多个常用的字符串操作函数,包括 `strlen`、`strcpy`、`strncpy`、`strcat`、`strncat`、`strcmp`、`strncpy`、`sprintf`、`itoa`、`strchr`、`strspn`、`strcspn`、`strstr` 和 `strtok`。每个函数均提供了语法说明、参数解释、返回值描述及示例代码。此外,还给出了部分函数的自实现版本,帮助读者深入理解其工作原理。通过这些函数,可以轻松地进行字符串长度计算、复制、连接、比较等操作。
    |
    3月前
    |
    C语言
    【C语言】字符串及其函数速览
    【C语言】字符串及其函数速览
    30 4
    |
    3月前
    |
    C语言
    【C语言篇】字符和字符串以及内存函数详细介绍与模拟实现(下篇)
    perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
    63 0
    |
    3月前
    |
    存储 安全 编译器
    【C语言篇】字符和字符串以及内存函数的详细介绍与模拟实现(上篇)
    当然可以用scanf和printf输入输出,这里在之前【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)已经讲过了,这里就不再赘述,主要介绍只针对字符的函数.
    55 0
    |
    5月前
    |
    C语言
    C语言学习笔记之初识字符串
    C语言学习笔记之初识字符串
    42 5