【C语言练习】字符串旋转你会嘛?

news2025/1/11 17:51:59

在这里插入图片描述
在这里插入图片描述

目录

  • 🍬题目描述:
    • 🍭思路一:
      • 🍡代码优化:
    • 🍭思路二:
  • 🍬题目描述:
    • 🍭思路一:
    • 🍭思路二:

🍬题目描述:

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

  • ABCD左旋一个字符得到BCDA
  • ABCD左旋两个字符得到CDAB

🍭思路一:

 要左旋 k 个字符,我们首先应该考虑左旋 1 1 1 个字符怎么做。左旋一个字符分为以下的三步:

  • 取出字符串中最左边的一个字符
  • 将字符串中剩下的字符按从左到右的顺序依次左移一位
  • 把第一步取出来的字符放到第二步结束得到的字符串的末尾

在这里插入图片描述

 知道左旋 1 1 1 个字符的做法,那左旋 k 个字符就只需要把上面的步骤重复执行 k 次就可以。分析的差不多了,接下来上代码:

void left_move(char arr[], int k)//k为左旋次数
{
	int len = strlen(arr);//计算字符串的长度
	int i = 0;
	for (i = 0; i < k; i++)//循环执行k次
	{
		//1:取出字符串中最左边的一个字符
		char tmp = arr[0];
		//2:将字符串中剩下的字符按从左到右的顺序依次左移一位
		int j = 0;
		for (j = 0; j < len - 1; j++)//除了第一个字符,还剩len-1个字符
		{
			arr[j] = arr[j + 1];
		}
		//3:把第一步取出来的字符放到第二步结束得到的字符串的末尾
		arr[len - 1] = tmp;
	}
}

int main()
{
	char arr[] = "ABCDE" ;
	left_move(arr, 2);
	printf("%s\n", arr);
	return 0;
}

🍡代码优化:

 上面的代码已经可以满足题目的要求,但是还可以进行优化。上面的字符串一共只有 5 5 5 个字符串,如果我们要左旋 7 7 7 个字符,那其实就相当于左旋 2 2 2 个字符。如果就按照上面的代码,那左旋 7 7 7 个字符可是要比左旋 2 2 2 个字符多浪贵一些时间,但它们两个最终得到的结果却是一样的,有没有什么办法能够把左旋 7 7 7 个字符变成左旋 2 2 2 个字符呢?答案是有的。这里问题的关键出在循环次数 k 的身上,当左旋 7 7 7 个字符时,只要让 k=2 就可以。因此我们可以在进入 for 循环之前加入下面这句代码: k%=len;。这样一来就可以大大优化代码的运行时间。分析的差不了,接下来上代码:

void left_move(char arr[], int k)//k为左旋次数
{
	int len = strlen(arr);//计算字符串的长度
	k %= len;//重中之重
	int i = 0;
	for (i = 0; i < k; i++)
	{
		//1:取出字符串中最左边的一个字符
		char tmp = arr[0];
		//2:将字符串中剩下的字符按从左到右的顺序依次左移一位
		int j = 0;
		for (j = 0; j < len - 1; j++)//出了第一个字符,还剩len-1个字符
		{
			arr[j] = arr[j + 1];
		}
		//3:把第一步取出来的字符放到第二步结束得到的字符串的末尾
		arr[len - 1] = tmp;
	}
}

int main()
{
	char arr[] = "ABCDE" ;
	left_move(arr, 7);
	printf("%s\n", arr);
	return 0;
}

 虽然优化后的代码,在某些情况下运行时间会有所下降,但整体来看,这种方法还是存在大量的字符移动,效率还是比较低的,接下来介绍一种更加高效的方法。

🍭思路二:

 思路二只需要对字符串进行三次逆序就可以。

  • 先逆序左边的 k 个字符
  • 再逆序剩下的 len-k 个字符
  • 最后逆序整个字符串

在这里插入图片描述
 以上动图就是左旋两个字符的过程。分析的差不多了,接下来上代码:

void reverse(char* left, char* right)//逆序函数,只要知道待逆序字符串中第一个字符的地址和最后一个地址就可以
{
	assert(left && right);//判断指针的有效性
	while (left < right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void left_move(char arr[], int k)
{
	int len = strlen(arr);
	k %= len;
	//1:先逆序左边的 `k` 个字符
	reverse(arr, arr + k - 1);
	//2:再逆序剩下的 `len-k` 个字符
	reverse(arr + k, arr + len - 1);
	//3:最后逆序整个字符串
	reverse(arr, arr + len - 1);
}

int main()
{
	char arr[] = "ABCDE";
	left_move(arr, 7);
	printf("%s\n", arr);
	return 0;
}

 本题到这里就结束了,在本题的基础上还衍生出来了下面这道题,还请各位看官继续往下看。

🍬题目描述:

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


🍭思路一:

 我们首先判断两个字符串的长度是否相等,如果长度不相等,那必不可能通过旋转一个字符串而得到另一个字符串。如果对于两个字符串 s1s2 ,它们的长度相等,那只需要取其中的一个字符串每次旋转一个字符,然后与另一个字符串比较,看是否相等,此时就可以用到上面的字符串左旋函数了。分析的差不多了,接下来上代码:

void reverse(char* left, char* right)//逆序函数,只要知道待逆序字符串中第一个字符的地址和最后一个地址就可以
{
	assert(left && right);//判断指针的有效性
	while (left < right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void left_move(char arr[], int k)
{
	int len = strlen(arr);
	k %= len;
	//1:先逆序左边的 `k` 个字符
	reverse(arr, arr + k - 1);
	//2:再逆序剩下的 `len-k` 个字符
	reverse(arr + k, arr + len - 1);
	//3:最后逆序整个字符串
	reverse(arr, arr + len - 1);
}

int is_left_move(char* s1, char* s2)
{
	//先判断两个字符串的长度是否相等
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	if (len1 != len2)//如果长度不相等就直接返回0
	{
		return 0;
	}
	int i = 0;
	for (i = 0; i < len1; i++)//对s1旋转,然后与s2比较
	{
		left_move(s1, 1);//每次旋转一个字符
		if (strcmp(s1, s2) == 0)
		{
			return 1;
		}
	}
	return 0;//代码执行到这里说明s1旋转了一轮和s2都不相等
}

int main()
{
	char s1[] = "AABCD";
	char s2[] = "BCDAA";
	int ret = is_left_move(s1, s2);
	if (ret == 1)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
	return 0;
}

 上面的代码可以实现题目的要求,但是这种方法比较依赖字符串旋转函数,接下来介绍一种更加巧妙地方法。

🍭思路二:

 在字符串 s1 的后面追加上 s1 ,得到一个新的字符串 s3 ,看 s2 是不是 s3 的一个字串,如果是,那说明 s1 可以通过旋转得到 s2 ,如果不是,那说明无法通过旋转 s1 得到 s2

在这里插入图片描述
 接下来上代码:

int is_left_move(char* s1, char* s2)
{
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	if (len1 != len2)//如果两个字符串的长度不相等就直接返回0
	{
		return 0;
	}
	char* s3 = strncat(s1, s1, len1);//strncat是字符串追加函数
	if (strstr(s3, s2) != NULL)//strstr是子串查找函数
	{
		return 1;//如果s2是s3的一个子串,说明可以通过旋转s1得到s2,就返回1
	}
	return 0;//如果代码执行到这里,说明s2不是s3的一个子串,说明不能通过旋转s1得到s2,就返回0
}

int main()
{
	char s1[20] = "AABCDF";
	char s2[] = "BCDFAA";
	int ret = is_left_move(s1, s2);
	if (ret == 1)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
	return 0;
}

🎶结语:
 今天首先介绍了两种旋转字符串的方法,思路一是比较常规的方法,思路二就比较巧妙,通过三次逆序就实现了字符串旋转,大大提高了效率。紧接着,在字符串旋转的基础上又介绍了:一个字符串能否通过另一个字符串旋转得到的问题,利用字符串自身追加结合查找子串巧妙地解决了这一问题。
 今天的分享到这里就结束啦,以上的内容如果对你有帮助的话,可以动动小手点赞、评论、收藏,你的支持就是我前进路上最大的动力!


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/193908.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

车辆控制器的 Fail Safe功能介绍

Fail Safe概要 在漆黑的夜路上&#xff0c;一辆开着头灯的汽车经过。 如果控制前照灯的控制器在这种情况下发生故障怎么办&#xff1f; 大灯会熄灭&#xff0c;造成危险吗&#xff1f; 不。 在这种情况下&#xff0c;控制器的“Fail Safe”被激活&#xff0c;前照灯保持其先前的…

企业需要一个数字体验平台(DXP)吗?

数字体验平台是一个软件框架&#xff0c;通过与不同的业务系统喝解决方案集成&#xff0c;帮助企业和机构建立、管理和优化跨渠道的数字体验。帮助企业实现跨网站、电子邮件、移动应用、社交平台、电子商务站点、物联网设备、数字标牌、POS系统等传播内容&#xff0c;除了为其中…

termux入门安装

下载安装 请使用F-Droid 的Termux&#xff0c;GooglePlay的 Termux 可能存在一些问题。 下载地址&#xff1a;https://f-droid.org/en/packages/com.termux/ 下载完成在安卓手机上直接安装Termux的apk文件就可以了。 termux换源 新版本的termux换源一条命令就可以超简单&…

【C++之类和对象】初识类和对象

目录前言一、面向对象VS面向过程二、类三、类的定义四、类的访问限定符五、封装六、C中的用struct和用class定义的类有何不同&#xff1f;七、类的作用域八、类的实例化九、计算类对象的大小十、this指针前言 C是一门面向对象的语言&#xff0c;之前学习的C语言是一种面向过程的…

对epoll的重新学习【附源码】

目录 一、概述 二、使用 三、API 3.1 epoll_create(int size) 3.2 epoll_ctl(int epfd,int op, int fd. struct epoll_event *event) 3.3 epoll_wait(int epfd, struct peoll_event *events, int maxevents, int timeout) 3.4 *ssize_t read(int fd, void buf, size_t c…

python模块之codecs

python 模块codecs python对多国语言的处理是支持的很好的&#xff0c;它可以处理现在任意编码的字符&#xff0c;这里深入的研究一下python对多种不同语言的处理。 有一点需要清楚的是&#xff0c;当python要做编码转换的时候&#xff0c;会借助于内部的编码&#xff0c;转换…

Spark读取Hive数据的两种方式与保存数据到HDFS

Spark读取Hive数据的两种方式与保存数据到HDFS Spark读取Hive数据的方式主要有两种 1、 通过访问hive metastore的方式&#xff0c;这种方式通过访问hive的metastore元数据的方式获取表结构信息和该表数据所存放的HDFS路径&#xff0c;这种方式的特点是效率高、数据吞吐量大、…

规则引擎-drools-4-动态生成drl文档

文章目录drools 引擎工作原理动态生成drl文件示例步骤模板文件 decision_rule_template.drt生成规则文件serviceDecisionNodeFact实体对象生成的drl字符串如下KieHealper 执行动态生成drl文件的原理实际应用过程中&#xff0c;很多时候&#xff0c;规则不是一成不变的&#xff…

54.Isaac教程--RealSense相机

RealSense相机 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录RealSense相机RealsenseCamera Codelet示例应用程序故障排除固件注意事项通过 USB 3.0 电缆使用 USB 3.0 端口x86_64 Linux 主机设置设置电源模型英特尔RealSense 435 摄像头…

分享159个ASP源码,总有一款适合您

ASP源码 分享159个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 159个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1EaQuRA6mxyylrNWLq8iKVA?pwdaljz 提取码&#x…

springmvc知识巩固

文章目录回顾spring知识前言什么是SpringMVCSpringMVC的优点SpringMVC的常用注解Controller注解的作用ResponseBody注解的作用SpringMVC重定向和转发SpringMVC主要组件SpringMVC的执行流程回顾spring知识 上篇整理了“spring知识巩固”常见面试题&#xff0c;有需要的伙伴请点…

Java基础:源码讲解Collection及相关实现List、Set、Queue

1 缘起 说到Java第一问&#xff0c;很多人的第一反应是三大特性&#xff0c;那么接下来&#xff0c;可能就是集合了。 Collection是Java必知必会&#xff0c;即使没有系统学习&#xff0c;在实际的开发过程中&#xff0c;Collection也是应用最广泛的。 当然&#xff0c;一般的…

ESP-IDF:归并排序测试

ESP-IDF:归并排序测试 /归并排序测试/ void printarry18 (int arr[],int length) { for(int i0;i<length;i) { cout<<arr[i]<<" "; } cout<<endl; } void merge(int arr[],int start, int end, int mid,int * temp) { int length 0;//记录te…

进程间通信之管道(匿名管道与命名管道)

进程间通信之管道进程间通信管道什么是管道管道分类——1.匿名管道匿名管道举例管道的特点管道分类——2.命名管道创建一个命名管道举例命名管道的打开规则匿名管道与命名管道的区别具体使用举例&#xff1a;例子1-用命名管道实现文件拷贝例子2-用命名管道实现server&clien…

POI介绍简介

2.1 POI介绍 Apache POI是用Java编写的免费开源的跨平台的Java API&#xff0c;Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能&#xff0c;其中使用最多的就是使用POI操作Excel文件。 jxl&#xff1a;专门操作Excel maven坐标&#xff1a; <depend…

Linux中安装MySQL及常见问题汇总

一、安装前工作 1、卸载之前的数据库 在安装前需要确定现在这个系统有没有 mysql&#xff0c;如果有那么必须卸载 &#xff08;在 centos7 自带的是 mariaDb 数据库&#xff0c;所以第一步是卸载数据库&#xff09;。 #查看mariadb数据库&#xff1a; rpm -qa | grep maria…

moment.js根据时间戳计算与当前时间相差多少天

Moment旨在在浏览器和Node.js中工作。 所有代码都应该在这两种环境中都有效&#xff0c;并且所有单元测试都在这两种环境中运行。 目前&#xff0c;以下浏览器用于ci系统&#xff1a;Windows XP上的Chrome&#xff0c;Windows 7上的IE 8,9和10&#xff0c;Windows 10上的IE 1…

小车程序、安装vs2019和必要的相关软件

环境 sqlserver2019 vs2019企业版本 安装vs2019步骤 小车程序 C# .net vs2019 sqlserver2019 小车程序地址 小车运行的几种轨迹 一&#xff0c;自动运行到指定节点 找到manual按钮&#xff0c;找到目的节点&#xff0c;search move。 二&#xff0…

[数学] 三次样条

三次样条 已知有一组点x0,x1,x2,⋯,xnx_0, x_1, x_2, \cdots, x_nx0​,x1​,x2​,⋯,xn​, 其中, xt<xt1x_t<x_{t1}xt​<xt1​, y(xt)yty(x_t)y_ty(xt​)yt​, 及该点处的切线y′(xt)yt′y(x_t)y_ty′(xt​)yt′​ 每两个相邻的点之间可以作一个三次曲线 在所有相邻…

let/const相关内容(二)

let/const作用域提升 1&#xff09;根据前面所学的内容知道&#xff0c;var定义的变量是可以作用域提升的。 console.log(foo); // undefined var foo "foo"虽然在第一行中foo还没有被定义&#xff0c;但是在执行代码前&#xff0c;会预编译&#xff0c;先定义f…