前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >力扣旋转字符串

力扣旋转字符串

作者头像
初阶牛
发布2023-03-08 14:43:42
2710
发布2023-03-08 14:43:42
举报
文章被收录于专栏:C语言基础C语言基础
目录

一、轮转数组

题目链接:(来源于力扣)(右旋) 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4]

方法一:暴力解题:

一位一位的移动,用循环完成移动一位的操作,一次交换相邻两个数. 例如:右移一位 数据:1 2 3 4 5 6 7 图解:

代码语言:javascript
复制
		右移一位过程图:
代码语言:javascript
复制
//右移一位操作
	for (i = numsSize - 1; i > 0; i--)
		{
			int tmp = nums[i];
			nums[i] = nums[i - 1];
			nums[i - 1] = tmp;
		}

右移k位(外层加一个k次循环) 注意:如果移动的位数是数字个数的整数倍数,则相当于没有移动,用k%numsSize可以避免没有必要的多余循环.

代码语言:javascript
复制
void rotate(int* nums, int  numsSize, int k)//外层循环
{
	int i = 0;
	k = k % numsSize;
	while (k--)
	{
		for (i = numsSize - 1; i > 0; i--)//内部循环
		{
		//交换
			int tmp = nums[i];
			nums[i] = nums[i - 1];
			nums[i - 1] = tmp;
		}
	}
}

小改进: 将内部的每次循环都要创建变量进行交换,改成直接覆盖,将最后一位数字拷贝一份后,将前面的数据直接向后面覆盖,最后将首位数据赋值为拷贝的最后一位数值也可以完成操作.

图解:

代码:

代码语言:javascript
复制
void rotate(int* nums, int numsSize, int k) {
	int i = 0;
	k = k % numsSize;
	
	while (k--)
	{
		int tmp = nums[numsSize - 1];//最后一位数字拷贝一份
		for (i = numsSize - 1; i > 0; i--)//内部循环
		{
			nums[i] = nums[i - 1];//前面的数据直接向后面覆盖
		}
		nums[0] = tmp;//首位数据赋值为拷贝的最后一位数
	}
	
}

但是,暴力解决,在面对大量的数据时,运行速度会慢很多,

方法二:三步翻转法.

其实有一个很神奇的现象,当我们需要右轮转 k 个位置时,可以将这个整形数组看作两部分 前半部分是:前n-k个数据,下标为[0,numsSize - k-1] 后半部分是:最后的k个数据,下标为:[numsSize - k,numsSize - 1] 然后分别逆序两部分,最后整体逆序就行了. 例如:数据1 2 3 4 5 6 7 逆序前半部分:4 3 2 1 5 6 7 逆序后半部分:4 3 2 1 7 6 5 逆序全部: 7 6 5 1 2 3 4

代码语言:javascript
复制
void reverse(int *arr,int left,int right)
{
	while(left<right)
	{
		int tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
void rotate(int* nums, int numsSize, int k){
    	if(numsSize==0)
	{
		return nums;
	}
    k = k % numsSize;
    reverse(nums, 0, numsSize - k-1);//逆序前半部分
	reverse(nums, numsSize - k, numsSize - 1);//逆序后半部分
	reverse(nums, 0, numsSize - 1);//逆序整体
}

二.左旋转字符串

传送门: 题目描述: 一个给定的字符序列 S ,请你把其循环左移 K 位后的序列输出 示例1:

输入: “abcXYZdef”,3

返回值: “XYZdefabc”

学完上面的数组右旋,相信左旋字符串应该可以照猫画虎吧!

同理使用:三步翻转法

代码语言:javascript
复制
 #include <string.h>
void reverse(char *arr,int left,int right)
{
	
	while(left<right)
	{
		char tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
char* LeftRotateString(char* nums, int k ) {
	int sz=strlen(nums);
	if(sz==0)
	{
		return nums;
	}
	k = k % sz;
	reverse(nums, 0, k-1);
	reverse(nums, k, sz - 1);
	reverse(nums, 0, sz - 1);
	return nums;
}

三:字符串旋转结果

题目描述: 自定义一个函数,要求判断一个字符串是否为另外一个字符串旋转之后的字符串。 要求这两个字符串长度相等. 返回值: 是: 返回1 不是:返回0.

示例1:

给定字符串s1 =AABCD和字符串s2 = BCDAA s1左旋2个数后可以得到s2,所以结果为真,返回1;

示例2:

给定s1=abcd和s2=ACBD, s1无法通过旋转得到,s2.结果为假,返回0;

思路一:

通过计算字符串长度得到sz,然后循环旋转sz次,每次旋转后与s2进行比较.

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <assert.h>
void reversed(char* left,char* right)
{
	assert(left);//防止传入空指针
	assert(right);
	while (left < right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
void left_revolve(char*arr,int k)
{
	int sz = strlen(arr);
	k %= sz;
		//逆序前k个
		reversed(arr, arr+k-1);
		//逆序后面剩下的
		reversed(arr+k, arr+sz-1);
		//逆序整体
		reversed(arr, arr + sz - 1);
}
int is_revolve(char* s1, char* s2, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		left_revolve(s1, 1);
		if (strcmp(s1, s2) == 0)
		{	
			return 1;
		}
	}
	return 0;
}
int main()
{
	char s1[50] = { 0 };
	char s2[50] = { 0 };
	gets(s1);
	gets(s2);
	int sz = strlen(s1);
	int ret = is_revolve(s1, s2, sz);
	printf("%d", ret);
	return 0;
}

思路2:

创建一个临时字符数组(tmp),将s1字符串拷贝两份存入临时字符数组. 使用strstr函数,判断字符串s2是否为tmp的字串.

涉及库函数: strcmp函数:字符串拷贝函数 strcat函数:字符串追加函数 strstr函数:查找子字符串函数.

这些字符串操作函数会在后续更新其使用方法,参数,以及模拟实现.

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define Max 100//定义零时字符串的最大长度
int is_revolve(const char* s1, char* s2,int sz)
{
	assert(s1 && s2);
	char tmp[Max];
	strcpy(tmp, s1);//将字符串1拷贝一份放入零时数组中
	strcat(tmp, s1);//使用字符串连接函数,将两个s1连接在一起
	if (strstr(tmp, s2) != NULL)//如果strstr函数返回的地址不是NULL说明,含有子字符串.
	{
		return 1;
	}
	else 0;//否则没有子字符串.
	
}
int main()
{
	char s1[50] = { 0 };//创建字符串s1
	char s2[50] = { 0 };//创建字符串s2;
	gets(s1);//获取字符串1
	gets(s2);//获取字符串2
	int sz = strlen(s1);//计算字符串长度
	int ret = is_revolve(s1, s2, sz);
	printf("%d", ret);
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、轮转数组
    • 方法一:暴力解题:
      • 方法二:三步翻转法.
      • 二.左旋转字符串
      • 三:字符串旋转结果
        • 思路一:
          • 思路2:
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档