PTA - 7-2 说反话-加强版 (15分) --- 新思路新理解

本文探讨了如何通过编程将英语句子中的单词顺序颠倒输出,对比了多种实现方法,包括使用双数组栈思想、去除多余空格的优化、以及利用输入特性简化代码的最终方案。

给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式:

测试输入包含一个测试用例,在一行内给出总长度不超过500 000的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用若干个空格分开。

输出格式:

每个测试用例的输出占一行,输出倒序后的句子,并且保证单词间只有1个空格。

输入样例:

Hello World   Here I Come

输出样例:

Come I Here World Hello

 

 

 


V1  ---最初的失败版本

 

我的思路:

old:  开两个足够大的数组,a,b。 用a读原文,然后从后往前遍历。不是空格,就按栈的思想,一个一个存到b中。top为栈顶。到达空格,则开循环将b中元素倒着输出。top归0 。 以此类推,直至循环走完。由于输入的开头经常是字符,导致最后一组不会输出,于是再外面又写了个小循环。这才完成。

而且,题中测试点多涉及空格,关于输不输空格,我补充条件相当吃力。就很难受。

好不容易修改完,最后一个点却超时。

源码:

#include<stdio.h>
#include<string.h>

int have(char a[],int n)
{
	int i;	
	for(i=n;i>=0;i--)
	{
		if(a[i]!=' ')
		{
			return 1;
		}
	}
	return 0;
}
int main()
{
	
	int i,top=0,j,flag=0;
	char a[700000];
	char b[600000];
	gets(a);
	
	for(i=strlen(a)-1;i>=0;i--)
	{
		if(a[i]!=' ')
		{
			b[top++] = a[i];
		}
		else if(a[i]==' '&& i+1<=strlen(a)-1 &&a[i+1]!=' ')   //有没有越界? 
		{
			for(j=top-1;j>=0;j--)
			{
				printf("%c",b[j]);
			}
			top=0;
			
			if(have(a,i)==1)
				printf(" ");			//多了个空格 
			if(i==0)
			{
				flag=1;
			}
		}
	}
	for(j=top-1;j>=0&&flag==0;j--)
	{
		printf("%c",b[j]);
	}
	
	return 0;
}

 

V2   ---- 学会了读入过程去空格

 

参考资源:https://www.cnblogs.com/lingr7/p/9432803.html

感谢原帖。

看了别人的代码,这才对于优化代码有了新的理解。

 

new:只开一个数组a。有预见性的在输入时就扔掉多余空格。输出时,遇到空格点直接把a部分输出即可。当然,我并非直接复制代码,而只是吸取了思路,掌握了精进的部分。

相比于之前。我才明白,有时候,代码写的少并不意味着计算量就小,以及运行时间更短。看似我在读a时只用了gets,简洁的不得了,之后却反而给我带来了更大的麻烦,使循环更加复杂。我应对空格的手段不太好,多写了一个数组,还多写了一个判断函数。确实不如原资料的楼主输入就剔除来的方便。

 

优化版本源码:

#include<stdio.h>
#include<string.h>

int main()
{
	
	int i,top=0,js,je,flag=0;
	char a[700000];
	char op;
	
	while((op = getchar())!= '\n')
	{
		if(op!=' ')
		{
			a[top++] = op;
			continue;
		}
		if(top==0 || a[top-1]!=' ')       //剔除多余空格 
		{
			a[top++] = op;
		}
	}
	a[top] = '\0';
	
	je = top-1;
	for(i=top-1;i>=0;i--)
	{
		if(a[i]==' ')
		{
			flag=0;
			for(js=i+1;js<=je;js++)    //js,je卡两端
			{
				flag=1;
				printf("%c",a[js]);
			}
			je = i-1;
			if(i!=0&&flag==1)            //应对特殊点
				printf(" ");
		}
	}
	
	for(i=0;i<=je;i++)                    //最后一个单词
		printf("%c",a[i]);
	
	
	
	return 0;
}

 

V3 ---V1思路+V2去空格方法

 

昨天考试,又遇到了这题。还是按着老办法走到了黑,正如初恋总是令人印象深刻,我也忘不掉这种古老的办法。

不过倒是过了。

源码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int i=0,top=0;
	char a[700000],b[700000];
	char ch,last=' ';
	
	while((scanf("%c",&ch))==1&&ch!='\n')   //去空格
	{
		if(ch==' '&&last==' ') continue;	
		a[i++] = ch;
		last = ch;
	}
	if(a[i-1]==' ')	a[i-1] = '\0';        //特殊的处理
	else
		a[i] = '\0';
	
	for(i=strlen(a)-1;i>=0;i--)            //依托于V1的栈的思路
	{    
		if(a[i]!=' ')
		{
			b[++top] = a[i];
		}
		else
		{
			for(int j=top;j>=1;j--)
			{
				printf("%c",b[j]);
			}
			top=0;
			printf(" ");
		}
	}
	for(int j=top;j>=1;j--)
	{
		printf("%c",b[j]);
	}
	
	return 0;
	
	
}

 

 

V4  ---最终版,我tm真没想到可以这么简单

 

今天听了讲解,才发现我可以利用这种特殊的输入。

每个串之间都有空格,一个或者多个。我跟本不用用特殊方法去掉。用单纯的scanf %s  或是 cin 这种遇空格结束的字符串读入方法直接就忽略了中间空格。

这样每次cin>>s ,s都是一个子字符串,我把一个子字符串看作栈的一个元素,一个一个入栈。最后再后进先出,输出出来,这就完啦。

这么简单,毫无道理可言。

ac代码

#include<bits/stdc++.h>
using namespace std;

string s[1000000];
string a;
int top=0;

int main()
{
	while(cin>>a)
	{
		s[++top] = a;
	}
	for(int i=top;i>=1;i--)
	{
		if(i==top)	cout<<s[i];
		else		cout<<" "<<s[i];
	}
	return 0;
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值