给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过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;
}
本文探讨了如何通过编程将英语句子中的单词顺序颠倒输出,对比了多种实现方法,包括使用双数组栈思想、去除多余空格的优化、以及利用输入特性简化代码的最终方案。
4390

被折叠的 条评论
为什么被折叠?



