• 【算法学习笔记】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的边界设置变量

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

  • 相关阅读:
    浅析Java源码之LinkedList
    浅析Java源码之ArrayList
    Vue源码终笔-VNode更新与diff算法初探
    Vue源码后记-更多options参数(2)
    Vue源码后记-更多options参数(1)
    Vue源码后记-其余内置指令(3)
    Vue源码后记-其余内置指令(2)
    Vue源码后记-其余内置指令(1)
    Vue源码后记-vFor列表渲染(3)
    Linux/CentOS 7 timezone 修改
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/4379272.html
Copyright © 2020-2023  润新知