• 倒置字符串不改变单词顺序的四种方法


    前言:题目来自牛客网 倒置字符串
    在这里插入图片描述

    第一种方法

    基本思路:
    第一种方法就是先逆置整个字符串I like beijing.逆置之后就是 .gnijieb ekil I
    然后再对每一组单词进行逆置就变成了 .beijing like I

    接下来我们再来谈一下,具体是怎么实现的
    首先我们要先逆置整个字符串就需要两个下标,一个指向I,一个指向结尾也就是 . 首元素和尾元素交换完之后,下标分别进行++和–,再来交换下一组元素,直到左下标大于右下标的时候(标志着交换已经全部完成了)结束循环
    这里我们把这部分封装成一个函数来实现,(因为在逆置单词的时候也会用到这个方法)下面会给出完整的代码

    void reverse(char* left, char* right)
    {
    	assert(left && right);
    
    	while (left <= right)
    	{
    		int ret = *left;
    		*left = *right;
    		*right = ret;
    		left++;
    		right--;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    接下来我们要考虑的就是如何逆置一个单词了
    我们同样可以参考上面的方法,给出两个指针,一个作为单词的开始标志,一个做为单词结束标志,如何再去调用上面的函数,这样就完成了我题目的要求,同样我们要考虑的是什么时候循环结束,我们仔细观察一下,当结尾遇到空格的时候就要停下来,完成一个单词的逆置,当遇到\0的时候,标志着整个逆置单词也完成了
    所以这时候我们就需要用到嵌套循环结构来完成这一过程

    下面第一种方法的具体实现

    #include 
    #include 
    #include 
    //先逆整个数组,再逆序单词
    
    void reverse(char* left, char* right)
    {
    	assert(left && right);
    
    	while (left <= right)
    	{
    		int ret = *left;
    		*left = *right;
    		*right = ret;
    		left++;
    		right--;
    	}
    }
    
    int main()
    {
    	char arr[101] = { 0 };
    	gets(arr);
    
    	int len = (int)strlen(arr) - 1;
    	先逆序整个字符串
    	reverse(arr, arr+len);
    
    	printf("%s\n", arr);
    	char* pc = arr;
    //  逆置单词
    	while (*pc)
    	{
    		char* start = pc;
    		char* end = pc;
    		while (*end != ' ' && *end != '\0')
    		{
    			end++;
    		}
    		reverse(start, end-1);//这里要end-1,因为你遇到空格停下来,如果不-1的话,就是把空格传过去了
    		//这里要判断一下是不是到了结尾
    		if (*end != '\0')
    			pc = end + 1;
    		else
    			pc = end;//如果end遇到\0,标志着单词逆置已经全部完成
    	}
    
    	printf("%s\n", arr);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    第二种方法

    然后第二种方法就是先逆置单词再逆置整个字符串,和第一种方法是一样的,这里我就不做过多的介绍了,直接给出大家代码看一下就OK了

    #include 
    #include 
    #include 
    
    //先逆序单词,再逆序整个数组
    void reverse(char* left, char* right)
    {
    	assert(left && right);
    
    	while (left < right)
    	{
    		char ret = *left;
    		*left = *right;
    		*right = ret;
    		left++;
    		right--;
    	}
    }
    
    int main()
    {
    	char arr[101] = { 0 };
    	gets(arr);
    
    	char* pc = arr;
    
    	//逆置单词
    	while (*pc)
    	{
    		char* start = pc;
    		char* end = pc;
    		while (*end != ' ' && *end != '\0')
    		{
    			end++;
    		}
    
    		reverse(start, end-1);//逆序单词
    		
    		if (*end != '\0')
    			pc = end+1;
    		else
    			pc = end;//如果end遇到\0,标志着单词逆置已经全部完成
    	}
    
    	//逆序整个字符串
    	int len = strlen(arr) - 1;
    	reverse(arr, arr + len);
    	printf("%s\n", arr);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    第三种方法

    第三种方法也是大部分人的想法,就是再创建一个大小相同的数组,然后后向前遍历整字符串数组,遇到空格就要遇到空格以后的内容放到新数组当中,然后打印新数组就行了

    不过大家要注意的是,这种方法是无法将第一个 I 放进新数组当中去的,因为我们是遇到空格之后,把空格以后的内容放进新数组当中,但是第一个单词之前是没有空间的,也就没法遇到空格,就没法将其放到新数组当中
    所以我们还需要一个从前往后遍历一次数组,不过要在遇到第一个空格之后就停下来
    第三种方法代码

    #include 
    #include 
    
    
    int main()
    {
    	char arr[101] = { 0 };
    	
    	char ch[101] = { 0 };
    	int start = 0;
    	
    	gets(arr);
    
    	int len = strlen(arr);
    
    	int i = 0;
    	int j = 0;
    	for (i = len; i >= 0; i--)
    	{
    		if (arr[i] == ' ')
    		{
    			for (j = i + 1; arr[j] != ' ' && arr[j] != '\0'; j++)
    			{
    				ch[start] = arr[j];
    				start++;
    			}
    			ch[start] = ' ';//因为数组当中没有放入空格,所以要在上述循环结束后自己放入
    			start++;//并++一次,以便下次存放单词
    		}
    	}
    	
    	//将第一个单词也放到新数组当中
    	for (i = 0; arr[i] != ' '; i++)
    	{
    		ch[start] = arr[i];
    		start++;
    	}
    	
    	printf("%s\n", ch);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    第四种方法

    第四种方法更为精简,不过也有一点点的瑕疵
    采用递归的方式,这个方法大家注意看注释就行了

    #include 
    
    //递归倒序打印
    void print()
    {
    	char arr[101] = { 0 };
    	if (scanf("%s", arr) != EOF)//scanf在读取输入缓冲区的时候,遇到空格和文件结尾标志(windows的文件结尾标志是^z)就会停下来
    	{
    		print();
    		printf("%s ", arr);
    	}
    }
    int main()
    {
    	print();
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    为什么说这个方法有一点小的瑕疵呢,是因为他在最后无论怎样都会多打印一个空格,但是并不影响最终的输出结果

    值得一提的是vs在输入文件结尾标志的^z时,需要输入三个才能让程序真正的停下来

    第四种方法的运行结果:
    在这里插入图片描述
    卑微求赞老铁们

  • 相关阅读:
    华为机试 - 勾股数元组
    (2022版)一套教程搞定k8s安装到实战 | 临时容器
    Bean 作用域和生命周期
    代理的常见问题汇总与分析处理
    DEC 深度编码聚类函数
    shell SQL 变量 Oracle shell调用SQL操作DB
    .Net 8.0 除gRPC之外的另一个选择,IceRPC之快速开始HelloWorld
    go get x509:certificate signed by unknown authority
    Python爬虫_Scrapy(一)
    Kubernetes--K8s基础详解
  • 原文地址:https://blog.csdn.net/Javaxaiobai/article/details/126236319