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

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

左旋转字符串

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

实现一个函数,可以左旋字符串中的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;
}

结果:
在这里插入图片描述

字符串旋转结果

写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。


例如:给定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;
}

结果:
在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陶来咯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值