算法

       算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落。许多学生看到一些公司在招聘时要求的编程语言五花八门,就产生了一种误解,认为学 计算机就是学各种编程语言,或者认为,学习最新的语言、技术、标准就是最好的铺路方法。其实,大家被这些公司误导了。编程语言虽然该学,但是学习计算机算 法和理论更重要,因为计算机语言和开发平台日新月异,但万变不离其宗的是那些算法和理论,例如数据结构、算法、编译原理、计算机体系结构、关系型数据库原 理等等。在“开复学生网”上,有位同学生动地把这些基础课程比拟为“内功”,把新的语言、技术、标准比拟为“外功”。整天赶时髦的人最后只懂得招式,没有 功力,是不可能成为高手的。
      算法与我当我在1980年转入计算机科学系时,还没有多少人的专业方向是计算机科学。有许多其他系的人嘲笑我 们说:“知道为什么只有你们系要加一个‘科学’,而没有‘物理科学系’或‘化学科学系’吗?因为人家是真的科学,不需要画蛇添足,而你们自己心虚,生怕不 ‘科学’,才这样欲盖弥彰。” 其实,这点他们彻底弄错了。真正学懂计算机的人(不只是“编程匠”)都对数学有相当的造诣,既能用科学家的严谨思维来求证,也能用工程师的务实手段来解决 问题——而这种思维和手段的最佳演绎就是“算法”。
       记得我读博时写的Othello对弈软件获得了世界冠军。当时,得第二名的人认为我是靠侥幸才 打赢他,不服气地问我的程序平均每秒能搜索多少步棋,当他发现我的软件在搜索效率上比他快60多倍时,才彻底服输。为什么在同样的机器上,我可以多做60 倍的工作呢?这是因为我用了一个最新的算法,能够把一个指数函数转换成四个近似的表,只要用常数时间就可得到近似的答案。在这个例子中,是否用对算法才是 能否赢得世界冠军的关键。
       还记得1988年贝尔实验室副总裁亲自来访问我的学校,目的就是为了想了解为什么他们的语音识别系统比我开发的慢几十 倍,而且,在扩大至大词汇系统后,速度差异更有几百倍之多。他们虽然买了几台超级计算机,勉强让系统跑了起来,但这么贵的计算资源让他们的产品部门很反 感,因为“昂贵”的技术是没有应用前景的。在与他们探讨的过程中,我惊讶地发现一个O(n*m)的动态规划(dynamic programming)居然被他们做成了O(n*n*m)。更惊讶的是,他们还为此发表了不少文章,甚至为自己的算法起了一个很特别的名字,并将算法提 名到一个科学会议里,希望能得到大奖。当时,贝尔实验室的研究员当然绝顶聪明,但他们全都是学数学、物理或电机出身,从未学过计算机科学或算法,才犯了这 么基本的错误。我想那些人以后再也不会嘲笑学计算机科学的人了吧!
网络时代的算法
        有人也许会说:“今天计算机这么快,算法还重要吗?”其 实永远不会有太快的计算机,因为我们总会想出新的应用。虽然在摩尔定律的作用下,计算机的计算能力每年都在飞快增长,价格也在不断下降。可我们不要忘记, 需要处理的信息量更是呈指数级的增长。现在每人每天都会创造出大量数据(照片,视频,语音,文本等等)。日益先进的记录和存储手段使我们每个人的信息量都 在爆炸式的增长。互联网的信息流量和日志容量也在飞快增长。在科学研究方面,随着研究手段的进步,数据量更是达到了前所未有的程度。无论是三维图形、海量 数据处理、机器学习、语音识别,都需要极大的计算量。在网络时代,越来越多的挑战需要靠卓越的算法来解决。
再举另一个网络时代的例子。在互联网和手机搜索上,如果要找附近的咖啡店,那么搜索引擎该怎么处理这个请求呢?
        最简单的办法就是把整个城市的咖啡馆都找出来,然后计算出它们的所在位置与你之间的距离,再进行排序,然后返回最近的结果。但该如何计算距离呢?图论里有不少算法可以解决这个问题。
        这么做也许是最直观的,但绝对不是最迅速的。如果一个城市只有为数不多的咖啡馆,那这么做应该没什么问题,反正计算量不大。但如果一个城市里有很多咖啡馆,又有很多用户都需要类似的搜索,那么服务器所承受的压力就大多了。在这种情况下,我们该怎样优化算法呢?
首先,我们可以把整个城市的咖啡馆做一次“预处理”。比如,把一个城市分成若干个“格子(grid)”,然后根据用户所在的位置把他放到某一个格子里,只对格子里的咖啡馆进行距离排序。
        问 题又来了,如果格子大小一样,那么绝大多数结果都可能出现在市中心的一个格子里,而郊区的格子里只有极少的结果。在这种情况下,我们应该把市中心多分出几 个格子。更进一步,格子应该是一个“树结构”,最顶层是一个大格——整个城市,然后逐层下降,格子越来越小,这样有利于用户进行精确搜索——如果在最底层 的格子里搜索结果不多,用户可以逐级上升,放大搜索范围。
       上述算法对咖啡馆的例子很实用,但是它具有通用性吗?答案是否定的。把咖啡馆抽象一下, 它是一个“点”,如果要搜索一个“面”该怎么办呢?比如,用户想去一个水库玩,而一个水库有好几个入口,那么哪一个离用户最近呢?这个时候,上述“树结构 ”就要改成“r-tree”,因为树中间的每一个节点都是一个范围,一个有边界的范围(参考:http://www.cs.umd.edu/~hjs /rtrees/index.html)。
       通过这个小例子,我们看到,应用程序的要求千变万化,很多时候需要把一个复杂的问题分解成若干简单的小问题,然后再选用合适的算法和数据结构。
并行算法:Google的核心优势
      上 面的例子在Google里就要算是小case了!每天Google的网站要处理十亿个以上的搜索,GMail要储存几千万用户的2G邮箱,Google Earth要让数十万用户同时在整个地球上遨游,并将合适的图片经过互联网提交给每个用户。如果没有好的算法,这些应用都无法成为现实。
       在这些的 应用中,哪怕是最基本的问题都会给传统的计算带来很大的挑战。例如,每天都有十亿以上的用户访问Google的网站,使用Google的服务,也产生很多 很多的日志(Log)。因为Log每分每秒都在飞速增加,我们必须有聪明的办法来进行处理。我曾经在面试中问过关于如何对log进行一些分析处理的问题, 有很多面试者的回答虽然在逻辑上正确,但在实际应用中是几乎不可行的。按照他们的算法,即便用上几万台机器,我们的处理速度都跟不上数据产生的速度。
那么Google是如何解决这些问题的呢?
        首 先,在网络时代,就算有最好的算法,也要能在并行计算的环境下执行。在Google的数据中心,我们使用的是超大的并行计算机。但传统的并行算法运行时, 效率会在增加机器数量后迅速降低,也就是说,十台机器如果有五倍的效果,增加到一千台时也许就只有几十倍的效果。这种事倍功半的代价是没有哪家公司可以负 担得起的。而且,在许多并行算法中,只要一个结点犯错误,所有计算都会前功尽弃。
那么Google是如何开发出既有效率又能容错的并行计算的呢?
        Google 最资深的计算机科学家Jeff Dean认识到, Google 所需的绝大部分数据处理都可以归结为一个简单的并行算法:Map and Reduce(http://labs.google.com/papers/mapreduce.html)。 这个算法能够在很多种计算中达到相当高的效率,而且是可扩展的(也就是说,一千台机器就算不能达到一千倍的效果,至少也可以达到几百倍的效果)。Map and Reduce的另外一大特色是它可以利用大批廉价的机器组成功能强大的server farm。最后,它的容错性能异常出色,就算一个server farm里面的机器down掉一半,整个farm依然能够运行。正是因为这个天才的认识,才有了Map and Reduce算法。借助该算法,Google几乎能无限地增加计算量,与日新月异的互联网应用一同成长。
        算法并不局限于计算机和网络
        举一 个计算机领域外的例子:在高能物理研究方面,很多实验每秒钟都产生几个TB的数据量。但因为处理能力和存储能力的不足,科学家不得不把绝大部分未经处理的 数据丢弃掉。可大家要知道,新元素的信息很有可能就藏在我们来不及处理的数据里面。同样的,在其他任何领域里,算法都可以改变人类的生活。例如人类基因的 研究,就可能因为算法而发明新的医疗方式。在国家安全领域,有效的算法可能避免下一个911的发生。在气象方面,算法可以更好地预测未来天灾的发生,以拯 救生命。
所以,如果你把计算机的发展放到应用和数据飞速增长的大环境下,你一定会发现,算法的重要性不是在日益减小,而是在日益加强。
给程序员的七个建议
      (1) 练内功。不要只花功夫学习各种流行的编程语言和工具,以及某些公司招聘广告上要求的科目。要把数据结构、算法、数据库、操作系统原理、计算机体系结构、计 算机网络,离散数学等基础课程学好。大家不妨试试高德纳所著The Art of Computer Programming里的题目,如果你能够解决其中的大部分题目,就说明你在算法方面有一定的功力了。
     (2)多实战。通过编程的实战积累经验、 巩固知识。很多中国大学毕业生缺乏编程和调试经验;学习C语言,考试过关就算学会了;课题项目中,只要程序能够编译,运行,并且输入输出满足要求就算了 事。这些做法是不行的。写程序的时候,大家必须多想想如何把程序写得更加精炼、高效、高质量。建议大家争取在大学四年中积累编写十万行代码的经验。我们必 须明白的是:好程序员是写出来的,不是学出来的。
     (3)求实干。不要轻视任何实际工作,比如一些看似简单的编码或测试。要不懈追求对细节一丝不苟 的实干作风与敬业精神。我发现不少程序员对于知识的掌握很肤浅,不求甚解,没有好奇心,不会刨根问底。比如,学会了C++,是否了解一个对象在编译后,在 汇编代码中是如何被初始化的?这个对象的各个成员在内存中是如何存放的?当一个成员函数被调用时,编译器在汇编代码中加入了哪些额外的动作?虚函数的调用 是如何实现的? 这些东西恐怕在编程语言或编译原理中都没有详细提到,只有通过踏实的实干才能真正掌握。
     (4)重视数学学习。数学是思维的体操,数学无处不在。学计算机至少要学习离散数学、概率论、布尔代数、集合论和数理逻辑。这些知识并不难,但是对你未来的工作帮助会很大。 尤其当你对一些“数学密集型”的领域如视频、图像处理等有兴趣时,这些知识将成为你手中的利器。
     (5)培养团队精神,学会与人合作。今天的软件工程早已经不是一个人可以单独操作的,而必须靠团队合作才能成功。不懂得合作的人是不能成大器的。大家要多去寻找可以与人一起做项目的机会。
     (6) 激励创新意识,培养好奇心,不要死记硬背。没有掌握某种算法技术的根本原理,就不会有应变和创新的能力。想成为一位好程序员(其实从事任何一个行业都是如 此),重要的是要养成钻研,好奇,创新,动手,合作的优秀习惯,不满足于填鸭,不满足于考试交差,不满足于表象。这不是学几门课能够一蹴而就的。
     (7) 有策略地“打工”。在不影响学业的前提下,寻找真正有意义的暑期工作或兼职。去找一个重视技术的公司,在一个好的“老板”指导下完成真正会被用户使用的程 序。不要急于去一个要你做“头”而独挡一面的地方,因为向别人学习才是你的目的。找工作也是一样,不要只看待遇和职衔,要挑一个你能够学习的环境,一个愿 意培养员工的企业,一个重视你的专业的公司。最后,还要挑一个好老板。
       希望大家都能把握机会,养成好的学习习惯,把算法学精学透;希望大家都能有一个美好的未来!
       所以大家加油哈~~~

 

       其实ACM比赛里面的谈的算法,和现代计算理论的发展还有一定方向的距离。
       举个例子,最近ICDE上提出的全世界“十大机器学习”算法,在ACM比赛里面看来,几乎都是连选拔赛都进不了的easy case。不少算法,基本上就是一个求和,相减,相除就可以完成的。为什么呢?
       现 在计算机学界的发展主流,早就不是细节计算过程的优化,而是针对新的,更好的计算模型,数学模型的提出和改进。数学模型,计算模型的研究,虽然实现的计算 过程很简单,但是代表的是一种思想,而不仅仅只是仅仅看成计算机内存单元之间的运算。比如一个朴素贝叶斯的提出,大家都知道其算法实现是多么简单吧,一个 刚学C语言的同学都会写,难道能说朴素贝叶斯是一个普通大一学生就能提出的吗?楼主说的别人实验室里面一个O(n*m)做成O(n*n*m)这样的情况其 实很多了,并不奇怪。这样就取笑别人,只能让自己捡了芝麻丢了西瓜。我们要学习的,应该是别人做的东西真正的精髓。多学习别人精髓方面做得出色的地方,而 不是具体实现的失误。实际上,很多顶尖的学术文章,在讲解算法的时候,往往都是以最简单,最直白的算法写出来,并不是别人不知道怎么优化,而是别人关键要 把整个计算的过程阐述清楚。具体实现的时候,你可以运用诸多的动态优化,各种树,各种表,去改进它的时间复杂度。这个在别人研究者面前,不是关心的主要问 题。
       大家都知道,在计算机领域,最一流的工作都是提出新的问题,二流的工作是提出一个计算模型去解决这个问题,三流的工作才是改进已有的解决办 法。中国人现在做科研的时候,往往都是在别人提出一种新的计算模型下,然后运用各种技巧改进别人实现过程。当然,这个工作也是值得称赞的。但是,这只是一 个三流工作。为什么中国不能出大师呢?
       不要觉得大学开的基础课程都是外功,只有算法才是内功。大学选择的这些课程,都是全世界最顶尖的计算机专家 共同协商的,全世界每个计算机本科都上这些课程。如果学好基本算法,就可以走遍天下都不怕的话,那为什么大学里面不主要就开算法课程?难道这些顶尖的计算 机专家都是故意让我们走弯路?其实不然,大学里面,关系数据库,计算机网络等,核心的内容在什么地方?绝对不只是算法的实现,而是解决模型的提出。比如 说,存储查询的关系模型,网络上的通讯,路由等模型。先提出了模型,才有实现的算法。这个模型不是上上算法课程就能学得会的。我知道ACM算法课里面也是 先讲解很多题目的解决模型,然后讲算法的。实际上解决任何一个问题都是如此。问题在于,大学的这些基础课程讲解的,是现实中用得最广泛的,相对有一套完成 的理论体系的。这些课程涉及面很广,任何一个领域都是足够让你消耗一辈子的精力去学习和研究。这些领域提出的各种问题,各种解决模型,不是ACM课上那种 光讲讲例题就能完了的,它们在现实应用广泛,问题很多,需要很深入地系统学习和研究,而不只是做几道编程题目就算是学会的。
       随便八卦一下,为什么ACM队伍里面那么多牛人,最后没几个选择从事到计算机的研究工作去呢?为什么大家都去做工程了?
    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值