旋转字符串问题-----左旋字符串

简介: 借助一个数组让它帮忙先放下不着急旋转的字符串,然后再将要旋转的字符放在后面,最后再拷贝回来

本篇总结了字符串旋转问题的几种解决方法,字符串左旋和右旋原理相同,会其一便可知其二,当然还有很多方法,我只列举相对容易理解的方法。


左旋转字符串


字符串旋转问题:字符串左旋


实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB


方法1:暴力旋转法


每次让字符串旋转一个,然后让旋转几个就循环几次。


思路:


1.拿走第一个字符

2.让数组后面的字符往前覆盖

3.让最后一个元素放入第一个字符


#include <string.h>
void left_move(char arr[], int k)
{
  int len = strlen(arr);
  k %= len;//当字符旋转次数为自己长度时,字符旋转跟没有旋转一样,(也就旋转回来了)
  //所以超过自身次数旋转跟某次旋转是一样的
  //第一步拷贝拿走第一个字符
  char tmp = arr[0];
  //第二步,将后面的往前覆盖
  int i;
  for (i = 0; i < len - 1; i++)
  {
    arr[i] = arr[i + 1];
  }
  //第三步,将第一个字符放在最后面
  arr[len - 1] = tmp;
}
int main()
{
  char arr[] = "ABCD";
  int k;
  scanf("%d", &k);
  left_move(arr, k);
  printf("%s", arr);
  return 0;
}


方法2:空间辅助法


借助一个数组让它帮忙先放下不着急旋转的字符串,然后再将要旋转的字符放在后面,最后再拷贝回来


思路:


1.创建一个数组空间

2.将不旋转的字符串先放进去

3.将要旋转的字符放在后面

4.将数组拷贝回来


void left_move(char arr[],int k)
{   //1.创建一个空数组
    char tmp[256] = { 0 };
  //旋转k 这个点是一个断点k后面的是不旋转的字符串,前面是旋转的字符
    //后面不旋转的拷贝到tmp中,
  strcpy(tmp, arr + k);
  //再将前面旋转的放进tmp后面
  strncat(tmp, arr, k);// strncat功能: 将arr中k个字符追加到tmp后面
  //再将tmp拷贝回去
  strcpy(arr, tmp);
}
int main()
{
  char arr[] = "abcdef";
  int k;
  scanf("%d", &k);
  left_move(arr,k)
  printf("%s", arr);
  return 0;
}


方法3:三步翻转法


对于这个方法我们可以这样想:


将一个字符串分成两个部分,X和Y两个部分,在字符串上定义反转(逆序)的操作为


X^T, 即把X的所有字符全部反转(逆序)【比如X=“abcd”,全部反转为 “dcba”,所以X ^T=“dcba”】,那么我们可以得到下面的结论:


 (X ^T Y ^T) ^T=YX.


所以显然就可以转换为字符串反转的问题了


思路也就是:


第一步逆序左边(k处为分界点)

第二步逆序右边

第三步逆序整体


void reverse(char *left,char*right)
{
  //逆序函数需要两个指针分别指向前面和后面,当前面指针小于后面指针时
  //说明还有元素需要逆序
  while (left < right)
  {
    char tmp = *left;
    *left = *right;
    *right = tmp;
    left++;
    right--;
  }
}
int main()
{
  char arr[] = "ABCD";
    int len = strlen(arr);
    int k=0;
  scanf("%d", &k);
  int k%=len;
  //写一个逆序函数reserve
  //先逆序左边
   reverse(arr,arr+k-1);
  //再逆序右边
   reverse(arr + k, arr + len - 1);
  //再整体逆序
   reverse(arr, arr + len - 1);
   printf("%s", arr);
  return 0;
}


结果:


1488399583b24b6f9f04ba0438778fd7.png


字符串旋转结果


写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC


这个也是字符串旋转问题,要求判断一个字符串是否是另外一个字符串旋转得到的


方法1:利用左旋字符串函数判断


思路:


我们可以利用上面的左旋字符的函数,让一个字符串每次旋转一次,每次旋转完后再与另外一个字符串比较,看是否相同。

当然有要注意的地方,当两个字符串长度都不一样大时,肯定不可能是旋转得到的。


#include <string.h>
void left_move(char arr[], int k)
{
  int len = strlen(arr);
  k %= len;//当字符旋转次数为自己长度时,字符旋转跟没有旋转一样,所以超过自身次数旋转跟某次旋转是一样的
  //左旋字符串
  //第一步拷贝拿走第一个字符
  char tmp = arr[0];
  //第二步,将后面的往前覆盖
  int i;
  for (i = 0; i < len - 1; i++)
  {
    arr[i] = arr[i + 1];
  }
  //第三步,将第一个字符放在最后面
  arr[len - 1] = tmp;
}
int is_move(char arr1[], char arr2[])
{
  int len1 = strlen(arr1);
  int len2 = strlen(arr2);
  if (len1 != len2)//判断一下长度是否相等,如果不等直接返回0
  {
    return 0;
  }
  int i;
  for (i = 0; i < len1; i++)
  {
    left_move(arr1, 1);//每次左旋一个
    if (strcmp(arr1, arr2) == 0)//每次旋转完与字符串2比较是否相同
    {
      return 1;
    }
  }
  return 0;
}
int main()
{
  char arr1[] = "ABCDEF";
  char arr2[] = "CDEFAB";
   int ret=is_move(arr1, arr2);
   if (ret == 1)
   {
     printf("Yes\n");
   }
   else
   {
     printf("No\n");
   }
}


方法2:空间辅助法


其实ABCDE无论怎么旋,旋转后的所有结果,都包含在了ABCDEABCD这个字符串里了。


所以做法很简单,只需要将原字符串再来一遍接在后面,然后找一找待查找的字符串是不是两倍原字符串的子集即可。


思路:


1.给字符串1自己追加一个自己字符串,然后拷贝到一个数组里

2.在追加后的字符串中找子符串中是否有与要比较的字符一样的


int is_move(char arr1[],char arr2[])
{
  int len1 = strlen(arr1);
  int len2 = strlen(arr2);
  if (len1 != len2)//判断一下长度是否相等,如果不等直接返回0
  {
    return 0;
  }
  char tmp[256]={0};//用一个辅助空间将原字符串做成两倍原字符串
  tmp=arr1;//将arr1中的内容拷贝到数组tmp中,因为tmp中空间足够大,可以给后面再追加len1个元素,因为arr1数组空间大小不知道,所有我们不能直接给arr1,追加自身字符。
  strncat(tmp, arr1, len1);//给数组tmp追加一个arr1,追加6个元素
  //strstr是用来查找字符串中的子串的,如果字符串中找到要比较的字符串
  //那么将返回要比较的字符在该字符串中的地址
  //如果没有则返回NULL.
  if (strstr(tmp, arr2) != NULL)
    return 1;
  else
    return 0;
}
int main()
{
  char arr1[] = "ABCDEF";
  char arr2[] = "CDEFAB";
  int ret = is_move(arr1, arr2);
  if (ret == 1)
  {
    printf("Yes\n");
  }
  else
  {
    printf("No\n");
  }
  return 0;
}


结果:


b4f65f5d1320465491418099b9140a97.png

相关文章
|
6月前
|
C语言
C语言--左旋字符/右旋字符实现及其判断
C语言--左旋字符/右旋字符实现及其判断
31 0
|
6月前
|
C语言
字符旋转及逆序输出问题
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。 例如:给定s1 =AABCD和s2 = BCDAA,返回1 给定s1=abcd和s2=ACBD,返回0.
|
2月前
|
存储 算法 索引
给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。如何解答呢?
给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。如何解答呢?
|
4月前
|
API
用栈翻转字符串
用栈翻转字符串
26 0
字符串左旋
字符串左旋
57 0
字符串左旋
【bilibilli】翻转字符串
【bilibilli】翻转字符串
力扣旋转字符串
力扣旋转字符串
95 0
每日一题——左旋转的字符串
每日一题——左旋转的字符串
|
C语言
一篇文章搞定字符串的旋转问题(数组旋转问题)!
一篇文章搞定字符串的旋转问题(数组旋转问题)!
79 0
剑指offer_字符串---字符串的排列
剑指offer_字符串---字符串的排列
51 0