题目链接:http://www.wikioi.com/problem/1205/
1.先分析一下自己的垃圾代码(通不过3.in)
#include <stdio.h> #include <string.h> char a[1000],b[1000]; //虽然b可以是int型的 但是无法判断长度 int main() { int i,j=0,al,bl; fgets(a,100,stdin); al=strlen(a); //记录空格位置 以此来隔断单词 for(i=0;i<strlen(a);i++) { if(a[i]==' ') b[j++]=i; } bl=strlen(b); //输出第一个单词 for(i=b[bl-1]+1;i<al;i++) //若用al-1 是因为最后一位是转行符? 提交时不行 printf("%c",a[i]); printf(" "); //输出中间段落 for(i=2;i<bl+1;i++) { j=b[bl-i]+1; if(j==b[bl-i+1])//此处是判断是否有多个空格相邻 好像有点多余 但是是由66分猜测的漏洞 结果不是这里 j++; else { for(;j<b[bl-i+1];j++) printf("%c",a[j]); printf(" "); } } //输出最后一个单词 for(i=0;i<b[0];i++) printf("%c",a[i]); }
可以看到,这是多么垃圾的代码。(一会和下面对比会更见鲜明)
只是用到了数组,和代号数组的方法来记录单词和空格的位置,一次循环遍历从而反转单词。
这几乎无算法可言,只是在解决问题,而非用艺术的方法去解决问题。个人理解算法是一种艺术。
留待以后检查为何通不过3.in (为了爬天梯,无耻地先搜索了一个C++的解法糊弄过关。。。)
2.接下来是让我十分惊喜的一个C++算法,让我第一次领略到了递归的魅力。
#include <stdio.h> #include <string> //不用string 无法CIN COUT #include<iostream> using namespace std; void execute() { string s; if(!(cin>>s)) return; execute(); cout<<s<<" "; } int main() { execute(); //getchar(); return 0; }
利用递归execute()函数循环地去读取单词,因为cin是可以判断空格结束输入的,所以只要有单词的输入就会返回1,遇到ENTER会返回0
以 i love you 举例
输入I love you,
程序先读入I,然后递归到下一层
下一层又读入love,然后又递归到下一层
然后读入you,继续递归到下一层
下一层递归没有输入了,于是返回,这一步极其重要
返回到上一层,输出you,然后返回,再上一层,输出love,再返回上一层,输出I
递归的理解还需要学习栈帧的知识,暂时我就先认为每一层调用execute()时 都会有一个新的栈帧,在这个栈帧中有不同的s,所以不会相互影响。还有就是想起了以前听老师说过“栈”的数据结构是,先进的后出,后进的先出,貌似已经有所体现了。
这才是艺术吧。如此简洁,如此可爱。干净利索,体现了思维上的高度,从数据结构的方面去思考存储和输出的问题。
{PS 以后研究为何通不过3.in时可以考虑从此代码深入对比分析,但是暂时还是不花费时间走那么深了,比较我这次主要还是以C为主要的学习对象}
3.另外可以再看几个不同的实现。一题多解应该是好处大大的。
此题解的 作者ID 叫何偷懒。
int main(){ string a,s;//第一步就看出来这算法不同寻常 s="";//初始化 while(cin>>a) { s=a+" "+s;//累加 <strong>反方向累加</strong>即可满足题意 } cout<<s; getchar(); return 0; }
这种思维看起来好像不是“正统”的解决问题,但实际上 我个人认为这是最优的解法,因为不用很复杂的知识就可以解决这种问题。
这种思维方式的重点,放在了对于输出结果的分析上。 输出的结果可以是单词和空格的累加,如同前两种做法,也可以是一整个已经完结的字符串。
对于字符串的生成是一个亮点,我一开始就想不到用反向累加的方式生成字符串。惯性思维使然阿。这就是逆向思维的完美诠释吧。
还有利用二维数组,和自定义结构的。二者类似。
自定义了一个结构叫做st 一个st的域里有一个char数组(字符串)
再在mian里搞了一个st的数组,暂时不懂为了不用二维数组非要这么做,貌似用二维数组的话都是char类型会出现问题?但是int也可以放在char里啊
也不懂为何不用while,而用这种类型的for//见到多次这么写的
利用i变量变化地输入单词于stu的每一个st的域中 注意写法 stu[i].a
排版有些问题 flag 用来判断开始的字符之前无空格。//小技巧需要掌握
此处还有一个巧妙之处在于i的使用。i并没有只在第一个for里使用过后就废弃,而是依旧接下来作为下一个for的边界设置变量
今天就写这么多。这几天一直没有敲代码,太懒了,鄙视一下自己先,执行力太低。