每日一题之旋转字符串(超详细,超硬核)

题目内容介绍(左旋转运算符)

实现一个函数,可以左旋字符串中的k个字符。

ABCD左旋一个字符得到BCDA

ABCD左旋两个字符得到CDAB

思路一:临时数组法1

  1. 数组arr数组中的内容要向前移动k位,前k位移到arr数组的末端。

  2. 首先创建一个和原数组arr等长的临时数组temp。

  3. 把arr数组中前k个元素赋值到temp数组的后k位。

  4. 然后将arr数组的前k位移到temp数组的前k位。这样旋转后的元素顺序就在temp数组中呈现。

  5. 再把temp数组中的整体内容赋值到原数组arr中。

    相关图解

    在这里插入图片描述

    代码实现

#include <stdio.h>
#include <string.h>
#include <assert.h>
void rotate(char* arr, int len, int k)
{
	assert(arr != NULL);  //数组长度不能为空
	assert(k <= len);     //传过来的k必须小于数组长度
	char temp[5] = { 0 };
	int i = 0;
    //将arr数组中的 前k位,移到临时数组的 后k位
	for (i = 0; i < k; i++)
	{
		temp[len - k + i] = arr[i];
	}
	//将arr数组中的 后k位,移到临时数组的 前k位
	for (i = k; i < len; i++)
	{
		temp[i - k] = arr[i];
	}
	//将temp数组中的内容,搬到arr数组中
	for (i = 0; i < len; i++)
	{
		arr[i] = temp[i];
	}
}
int main()
{
	//先把arr中前k个字符,赋值到temp中的后面,然后将arr中k的后几位,移到temp的前几位
	char arr[] = "ABCD";
	int len = strlen(arr);
	int k = 0;
	scanf("%d", &k);  //向前移动的位数
	rotate(arr, len, k);
	printf("%s", arr);
	return 0;
}

思路二:临时数组法2

  1. 建立一个临时数组

  2. 把arr数组中的前k位(含k位)先转移到数组中去。

  3. arr数组的前k位(含k位)位置此时已经空缺,把arr数组中的后k位,向前移动k位

  4. 然后再把临时数组中的内容附到arr数组的后面

    相关图解:

在这里插入图片描述

代码实现:

#include <stdio.h>
#include <string.h>
#include <assert.h>
void rotate(char* arr, int len, int k)
{
	assert(arr != NULL);  //传入的数组不能为空
	assert(k <= len);   //传入的旋转数必须小于等于字符长度
	char temp[5] = { 0 };  //建立一个临时数组, 
	int i = 0;
	//用临时数组,存 前k个 arr数组中的元素
	for (i = 0; i < len; i++)
	{
		temp[i] = arr[i];    
	} 
	//然后把arr剩下数组中的元素,向前移动k位
	for (i = k; i < len; i++)
	{
		arr[i - k] = arr[i];
	}
	//把临时数组中的数字 插入到arr数组中
	for (i = len - k ; i < len; i++)
	{
		arr[i] = temp[i - (len - k)];
	}
}
int main()
{
	char arr[] = "ABCD";
	int len = strlen(arr); //计算字符串长度
	int k = 0;
	scanf("%d", &k); //向做先转k个字符
	rotate(arr, len,k);
	printf("%s", arr);
	return 0;
}

思路三:临时变量循环法

  • 上面的两种算法都有着相同的缺陷,那就是要建立一个临时数组,而且还要限定临时数组的长度,这样就严重影响了算法的灵活性,还提高了空间复杂度,
  • 下面是第三种算法,它降低了空间复杂度
  1. 依次从arr数组中提取前k个元素,每次提取一个
  2. 提取的过程中,把后k个元素向前移动
  3. 把提取到的元素,依次添加到arr数组之后

相关图解:
在这里插入图片描述

代码实现:

#include <stdio.h>
#include <string.h>
#include <assert.h>
void rotate(char* arr, int len, int k)
{
	assert(arr != NULL);
	assert(k <= len);
	int i = 0;
	for (i = 0; i < k; i++)
	{
		char temp = arr[0];
		int j = 0;
		for (j = 0; j < len-1; j++)
		{
			arr[j] = arr[j + 1];
		}
		arr[len - 1] = temp;
	}
}
int main()
{
	char arr[] = "ABCDE";
	int k = 0;
	scanf("%d", &k);//要移动的位数
	int len = strlen(arr);
	rotate(arr, len, k);
	printf("%s", arr);
	return 0;
}

思路四:块变换(求逆)

  • 前两种算法是提高了空间复杂度 但降低了时间复杂度
  • 第三种算法是提高了时间复杂度 但降低了空间复杂度
  • 到底有被有一种空间和时间复杂度相对较低的算法呢,那肯定是有滴!
  1. 第一步:将前k个字符两两进行翻转。
  2. 第二步:将后k(含k)个字符进行翻转。
  3. 第三步:将字符整体进行翻转。

相关图解:

在这里插入图片描述

代码实现:

```c
 #include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char* left,char* right)
{
	while (left < right)
	{
	char temp = 0;
	temp = *left;
	*left = *right;
	*right = temp;
	left++;
	right--;
	}
}
void rotate(char* arr, int len, int k)
{
	assert(arr != NULL);  //传来的字符串数组不能为空
	assert(k <= len);     //传来的移动位数,必须小于字符串长度
	//旋转前k个元素
	reverse(arr,  arr + k - 1);
	//旋转后k(含k)个元素
	reverse(arr + k , arr + len - 1);
	//旋转整体元素
	reverse(arr, arr + len - 1);
}
int main()
{
	char arr[] = "ABCD";
	int k = 0;
	scanf("%d", &k);//字符向左旋转k位
	int len = strlen(arr); //字符长度
	rotate(arr, len, k);
	printf("%s", arr);
	return 0;
}
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小周学编程~~~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值