【算法学习笔记】02.wikioi1205 单词翻转

题目链接: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的边界设置变量

今天就写这么多。这几天一直没有敲代码,太懒了,鄙视一下自己先,执行力太低。

原文地址:https://www.cnblogs.com/yuchenlin/p/4379272.html