杯具是如何产生的——读《转:迅雷亲历面经:笔试+上机+面试(完整JAVA面试题求解大讨论)》有感。
原文链接:
http://topic.csdn.net/u/20091129/21/4bbf398d-431a-4f8e-accc-b8de6572b8af.html
to原文171楼lianghua19:你的回复埋得太深了,要是一开始就看到大大的回复,我就懒得再回复了。
to原文551楼gz116:谢谢大大的支持。    读《转:迅雷亲历面经:笔试+上机+面试(完整JAVA面试题求解大讨论)》有感。
昨天晚上看了这个帖,对于编程题中一道算法题很有兴趣,思考了一下后又简单看了一下各位大大回复中提供的解题算法,深有感触。算法题如下。
2)假如有字符串“6sabcsssfsfs33” ,用最有快速的方法去掉字符“ab3”,不能用java内置字符串方法(indeOf,substring,replaceAll等)? 有感于各位大大的回复,编写了以下故事:杯具是如何产生的
    一天,客户a在使用软件公司B为他制定的一个软件,在使用过程中,他发现一个页面中有一个字符串显示错误:在这一页中需要将前一页中传进来的字符串删除几个字母,用以表示处理完毕,但是在软件制作时忘记对这个字符串进行处理了。于是他通知软件公司B对这个软件进行修改。    不幸的是,原来的软件开发小组因为这个软件的成功,都升职到管理层了。重组后的开发小组的需求分析员c找到了客户a了解修改需求。    因为客户a在当初开发软件时也参与到了其中,对编程有一点点了解。他知道那个字符串是用一个叫做变量的东西保存着的。但是他忘记了如何修改那个叫做变量的东西。于是他对分析员c说描述说他需要将程序中的字符串“6sabcsssfsfs33” 去掉字符“ab3”。需求分析员c如实的记录了客户a的需求,交给了开发小组的头头系统设计师d。    系统设计师d是一个经验丰富的系统设计师,他做过无数个项目,无论小的大的,对编程从底层到高层都有十分深刻的理解。他仔细分析了客户需求。发现只是一个很简单的功能修改,于是叫来开发小组的新丁程序员e,将这项任务交给他。    系统设计师d根据长期积累的经验,知道客户的需求总是在变的。也许今天要去掉字符a,明天要插入字符b,后天要将字符c替换成字符d,所以让新丁程序员e将这个功能应用抽象的的方法,编写成一个通用可变的模块。另外根据他的长期编程经验,XX语言的有一个内置字符串方法有时候并不可靠,上次就因为这个情况导致了一个系统出现了严重的bug,最后他亲自主刀,奋斗了一天一夜才把这个bug揪出来。于是他特别叮嘱新丁程序员e(也许是为了卖弄)绝对不要用XX语言的内置字符串方法。    新丁程序员e是一个十分聪明的程序员,虽然他还没有什么做项目的经验,但是他在学校学了很多东西,对各种深奥的算法都有研究。他接到这个任务后,认为这正是证明自己能力的机会。于是为了完成任务,他使出浑身解数,什么冒泡法啊,哈希表法啊,两分法啊全都用上了。    一个星期后,他自信满满的将数百行的程序交给测试员f。测试员f是一个老成稳重的程序员。他看到新丁程序员e那年轻人的浮躁与盲目自信,于是打算给他一个深刻的教训,灭灭他的浮躁气。经过他的严格测试。数千行的程序里面发现了大大小小小160多个bug,其中最严重的是:当字符串的长度超过1G后,会因为溢出导致系统彻底崩溃。新丁程序员e看到了长长地bug报告单,很受打击。但是年轻人就是有一股劲,越是打击越有干劲。于是他与测试员f对上了。    如此一来一回,经过了一个多月,新丁程序员e的代码终于通过测试了。同时他的代码长度也膨胀到了几千行。    新丁程序员e将代码交给系统设计师d。系统设计师d对新丁程序员e完成这么一个小功能都用了差不多2个月不太满意,但是新人嘛,没什么经验,随便训训就算了。    从叫软件公司B修改软件上的一个拼写错误,到客户a拿到修改好后的程序,足足过了2个月。虽然客户a对修改这么简单的一个错误,软件公司B用了这么长的一段时间,很是抱怨。但是因为他对软件编程如同云中雾里,所以也没什么办法。    后记:有一天客户a偶尔碰到了原来的软件开发小组成员g,此时原小组成员g已经是公司的一个部门经理了,谈到了这件事(客户a的那点皮毛编程知识就是向他学的),部门经理g惊讶的说:我的天啊,要修改这个错误不是只要一个赋值语句 aa = "6scsssfsfs";就行了吗?怎么弄了两个月,写了几千行的代码?
    以上故事,虽然情节有些夸张了,但相信,在我们身边已经发生过了无数次类似的故事,而且将来还会继续发生。杯具啊杯具……

    也许有些大大认为上题的解法只是一种取巧,或者是一种外行人的解法。
   那么请看看我站在程序员的角度是如何思考这个问题的求解的。
    1.在看题目前先在心中默念三遍程序员圣经:
世间一切问题都是时间与空间的问题,时间与空间是可以等价互换的 。
(世间一切皆空,一切皆色, 色即是空,空即是色)

    2.仔细阅读题目,分析需求,发现:
要处理的空间确定:字符串“6sabcsssfsfs33”(不是处理任意一个空间(变量))
处理规则确定去掉字符“ab3”(不是去掉任意指定字符)。

    3.翻开编程葵花宝典字符串篇第一页,上写道:
道生一,一生二,二生三,三生万物——字符串处理三大招式:乾坤大挪移、一力降十会,移花接木。

    4.分别套用上面三大式得解题过程如下:
        (1)乾坤大挪移
            因处理对象已确定,处理规则已确定,故可直接得出处理步骤:
    1.截去字符串最后两个字符“33”
            2.从字符串第五个字符“c”开始,将后面的字符整体向前移动两位(去掉字符“ab”)
            至此处理完成,收功。

        生活类比1:买裤子,发现长了些,售货员帮帮忙将其截取。
        生活类比2:将扑克牌排序发现黑桃A插入了方块五和梅花六之间,将其取出排放到前面。

        (2)一力降十会
            因处理对象已确定,处理规则已确定,故可直接算出处理结果:“6scsssfsfs”,步骤:
            1.直接将处理结果依次填入原字符串中,将原数据覆盖。
            至此处理完成,收功。

        生活类比1:扑克牌排序实在是太乱了,将其摊开到桌面,从小到大依次拾起扑克牌。

        (3)移花接木
            原因类同一力降十会,步骤:
            1.改变指向“6sabcsssfsfs33”的字符串,指向正确结果“6scsssfsfs”
            至此处理完成,收功。

        生活类比1:买衣服,发现大小不合身,售货员换了一个型号合适的。
        生活类比2:不用自己动手给扑克牌排序,直接买副新的。(新的扑克牌一开始就是排序好了的)

        对以上三个方法进行优劣评价:
        (1)乾坤大挪移
            优点:对于简单的字符串,快速直接。
            缺点:需要事先得出操作步骤,对复杂的操作步骤,要牺牲时间,不适合应对巨大的字符串。

        (2)一力降十会
            优点:简单直接,在复杂而又不可避免时空消耗的情况下,也许这个是最简单直接的方法。
            缺点:时空消耗巨大。        (3)移花接木
            优点:灵活优雅。
            缺点:需要环境支持,实际上并未修改原来的字符串,若有多个指针同时指向它,那么还是原来的结果。

    5.根据上面分析,发现最简单的就是用赋值符号“=”将正确结果赋给原字符串。    至于使用赋值方法,具体实际是用到一力降十会还是移花接木的方法,因为没有仔细研究过java的实现基础,就不得而知了。对于不同的语言与编译器版本,加上计算机结构的限制(在哈佛结构下,编译器作者又将代码中嵌入的常量归类到了代码段……),分别选用了两种方法。


    本人处女贴,请各位大大尽情拍砖。