经过一年多的编写和准备,《算法的乐趣》终于出版了,4月中旬开始可以在京东、当当等网店购买,实体书店上架可能会慢一点。感谢图灵社区的各位老师的辛勤耕耘,也感谢《啊哈!算法》作者纪磊先生(啊哈磊),LinkedIn高级主任分析师王益先生,极光推送首席科学家黄鑫先生(飞林沙)为本书热情作序并给予充分的肯定。
序一
读《算法的乐趣》的乐趣超出了我的预料。
说到算法,大部分计算机专业的同学的第一反应估计是MIT出版社的经典教材《算法导论》(Introduction to Algorithms)。这是一本由浅入深的好书,堪称“神书”——别看书挺厚,但是对初学者来说很难弄懂的问题也娓娓道来,让人看一遍就明白;而且作者用最简单的英语词汇和句法写书,以至于世界各地的学生们,不需要英语很好,即可读懂原版。只是看完这本大部头之后,总有一些意犹未尽的感觉——对我们日常生活中常见的比如音乐播放器里以及电子游戏里的算法并没有太多介绍。而这些正是《算法的乐趣》中主要的部分。
在Amazon上,另外两本排名靠前的经典算法教材是Jon Kleinberg的《算法设计》(Algorithm Design)和Steven S. Skiena的《算法设计手册》(The Algorithm Design Manual)。这两本出自名家之手的教材和很多教材一样,按照算法的类型或者背后的设计思路来组织内容。这是教材应该做的,“授人以鱼不如授人以渔”,传授思路而不是算法本身是教材的写作目的。可是算法最有意思的地方首先在于算法本身,因为算法是为了解决实际问题而设计的,所以让大家认识到算法奥妙的自然顺序应该是先展示有趣的问题,再展示优雅的算法,最后归纳设计思路。而这正是《算法的乐趣》吸引人的地方。说到乐趣,总让我想起我学习和使用数学知识的经历。虽然我的学位是关于统计机器学习的,而且毕业后一直从事相关工作,但是我从小学一年级到博士第三年都对数学毫无兴趣,因为学校的老师和数学成绩好的同学都说不明白数学的用处,以至于我一直以为数学的作用只是锻炼和展示自己的聪明,博得老师的表扬,成为陈景润那样为国争光的英雄。而这些对我实在没有吸引力,而且我认为恐怕对绝大部分学生都没什么吸引力。
我认识到数学的价值,是因为在博士第三年把研究方向换到了统计机器学习。在读教材的时候,我曾想验证“数学无用”,所以费尽心力地试图写一个程序来判断一个64×64像素的图片里到底是数字“1”还是数字“9”,却发现无论如何也很难写一个有效的程序;可是利用教材里的数学知识却能设计和“训练”一个数学模型,准确地识别任意字符。因为体会到了数学的用处,我兴奋地用了一年的时间复习大学本科的数学课程,然后才读懂了人工智能的专业教材和论文。此后才有所创新,发表论文,到博士毕业。这整个过程用了三年,而效果超过了之前19年数学教育的效果。
在这个过程中,我自然而然地开始注意数学知识的前因(比如为什么人们会关注长度、面积,怎么会有人考虑勾股定理这样的规律)以及后果(今天的数学知识能给物理学和机器智能带来什么样的帮助),也开始归纳和了解各种数学系统背后的规律,能体会哥德尔定理阐述的意思。当然,也破除了“数学是各种科学之母”之类的迷信,数学当然不是“科学之母”,而是“科学之子”,是先有物理学、力学和天文学,才有的数学;先有应用场景后有工具,先有探索后有归纳。
算法也是如此。先有工程问题需要解决,算法是解法,设计算法是寻求解法。虽然算法作为一门科学是归纳寻求解法的思路,但学习这种归纳法的前提是能体会各种具体算法的用处和效果。意识到这一点,自然也就破除了诸如“学好数学才能学好算法”之类的迷信。而把算法解决的各种有趣问题罗列出来,把算法的可爱之处展示给愿意发现和体会生活中点滴乐趣的读者们,正是《算法的乐趣》在技术价值之外的一层社会价值。
十年前,当我们坐在课堂里学习算法的时候,我们学到的是如何用人脑寻求解法,然后把解法写成程序,让计算机照着执行去解决问题。这是“经典算法”。最近十几年,随着Internet产业的兴起,Internet服务在不断取代原来由人提供的服务,这就要求机器拥有一定程度上能取代人的“智能”。在搜索引擎、推荐系统和广告系统等各个领域里,类似上述“识别数字”的问题越来越多,而人工智能和机器学习的应用也越来越深入我们的生活。机器学习算法的设计目标和“经典算法”不同——不是让人来想解法,而是让计算机从数据归纳知识——有了这些知识,计算机就能自己寻求解法。
虽然经典算法和机器学习算法之间的差别大得如同一场革命,但是由经典而入机器学习的过程却是自然而然的。比如《算法的乐趣》中介绍的曲线拟合问题,就是supervised learning(有监督学习),而音乐播放器里常用的傅里叶变换和其他时域频域变换则是unsupervised learning(无监督学习)的技术基础,棋类游戏算法是博弈论和reinforcement learning(强化学习)的经典例子。我常见有朋友从读数学教材开始探索机器学习和人工智能算法,也常看到有人不堪忍受长时间缺乏乐趣的探索以至于半途而废。如果是这样,也许不如从《算法的乐趣》开始这个探索过程。
我曾经以为从乐趣出发阐述算法的书会从西方发芽,没想到先看到了一本中文书。这真超出了我的预料。
王益
LinkedIn高级主任分析师
序二
当图灵出版社的编辑找到我希望我为这本书写个序的时候,我和旁边的同事调侃了一句:又一本简版的《算法导论》要诞生了。但是我还是下载了附件阅读了这本书,当翻到目录的时候,我的兴趣就被燃起来了,转头和同事说,也许这是一本不错的书。
程序员到底需不需要学习算法?这个问题被争论的次数绝对不亚于“Java是不是最好的语言”“VIM和Emacs谁是最好的编辑器”“程序员是不是需要学习数学”。为了避免陷入这样的争论里,我们先对“算法”一词做个转换定义,什么是算法?下面我举几个我亲身经历的例子。
有一次我们发布了一个APP,在注册时要求用户输入自己的真实姓名,但是粗心的工程师忘记了要求用户填写自己的性别,更可怜的是在欢迎页上面明晃晃地写着“欢迎XXX先生注册XX网”,可是应用已经发布到了App Store,到底怎么办?有一位工程师提出了一个办法,我们根据已有的用户姓名和性别作为训练集,来预测新用户到底是男还是女,为了让这个错误尽快得到修复,我们使用了最简单的朴素贝叶斯分类算法,最终测试集上的预测准确率达到93%,也就是说我们解决了93%用户的体验问题。我把这类算法称为专业类算法,也就是招聘网站上算法工程师要求的算法,例如图像处理工程师、数据挖掘工程师等。
有一次我们有一个相似性搜索的需求,数据量不大,只有几万条的数据记录,没有必要用ES这样的搜索引擎。例如输入“长沙市”, 也希望可以找到“我爱湖南长沙”“沙市小吃”等,且不说这个需求是否合理,我们单纯来讨论这个问题的解决方案。工程师实现的第一版是将所有字的组合全部列举出来,然后在数据库里做like操作,性能无法接受。于是我们提出了另一种解决方案:将数据库中的每个词都拆成单字,做成集合,保存在缓存中。接下来只需要对集合做交集操作,以字为单位计算词与词之间的相似性,性能问题一下就解决了。这种解题思路在《编程珠玑》中屡见不鲜,这不足以称为具体的算法,几乎都是在梳理我们的逻辑,训练我们解决问题的能力,我把这类算法称为逻辑类算法,或者技巧类算法。
还有一次,我们有个需求是帮助用户做旅游的行程规划,其中的情况比较复杂,因为除了地理位置之外,还需要包含目的地的过往用户评价、所需耗时、不同城市的住宿花费等。但是如果我们仔细分析,可以基于产品设计去拆分问题。在在线部分,我们可以去使用基于路程的最短图路径算法,或者基于价格的贪心算法,也可以在综合排序处为用户选择使用了变形加权的最短图路径算法。在离线部分,由于图的节点和边都较少,可以使用穷举法来为用户找到几种不同类型的最优解。这些算法都是在《算法导论》和《数据结构》中有着详细讨论的算法,书中的每一个算法和数据结构都是作者多年来抽象总结出的通用思路,我称之为通用类算法。
再说一个最基本的,我们做一个网站允许用户发布状态,在高峰期并发量太大,数据库不堪重负,所以我们需要将用户的插入记录先存入到消息队列中,保证用户的正常使用,然后再落地到MySQL数据库中。大家都会想到选择队列这样一种先入先出的数据结构,这也属于一种算法。
通过上面的几个例子,你会不会觉得你的身边处处都是算法?那么到底什么是算法?我们看看标准的定义:能够对一定规范的输入,在有限时间内获得所要求的输出的一系列指令都叫作算法。这个定义太抽象了,让我们简单来说,算法其实就是解决问题的思路和办法。那么从这一点来说,你还会说算法不重要么?
那么为什么还会有很多学生,甚至已经工作了很久的朋友还会说大学学的东西没有意义,算法没有用呢?归根结底是因为大家不知道为什么学,或者说缺乏算法的场景化。我在读大学的时候,经常做一些简单的网站,用到的技术无外乎是最简单的对数据库的增删改查,当时最大的感觉就是算法没有用。后来随着工作的深入,我开始逐步地意识到算法的重要性,逐渐地把算法捡了起来。
这本书给我最大的惊喜是没有像一般的算法书一样单纯地去讲算法和数据结构本身,那样无论语言多风趣,只要一谈到关键的问题也会马上变得无趣起来。作者在每一章都给出了一个实际的问题,然后尝试用算法去解决这一个问题,没有局限于通用类算法,而是同时涵盖逻辑类算法、通用类算法和专业类算法,真正是在训练读者解决问题的能力,而解决问题的能力,正是任何一家公司所需人才的最核心的技能。
另外,我已经在幻想作者在下一本书里可以把工作中的实际场景列举出来,更进一步地讲述工作中的算法,让每一个在校学生都可以意识到算法对于未来工作的重要性,也让每一位从业者拍案叫绝:“原来这个问题可以这样解!”让人人谈算法,人人写算法,引发软件行业的全民算法潮。
黄鑫(飞林沙)
极光推送首席科学家
序三
如果说《啊哈!算法》是算法界的小白书,内容太少看得不过瘾,那么这本《算法的乐趣》或许可以带你一起牛逼一起飞。当我刚拿到书的目录的时候,我就很期待,因为终于有一本算法书可以系统地和大伙说一说这些我也很想与大伙说的伟大算法。
暴力盲目的搜索算法往往让计算机显得很笨甚至有点痴呆,如果你想设计一个“狡猾”的程序,那么本书中的搜索剪枝、A*寻径、博弈树以及遗传算法等将给你带来启发。快速傅里叶变换,这么霸气而又高大上的名字,其实在我们生活中的应用随处可见,家中的Wi-Fi、智能手机、电话、路由器等几乎所有内置计算机系统的东西都会以各种方式使用这个算法。RLE数据压缩算法,在文档、视频、音乐、数据存储、云计算、数据库等几乎所有应用中都有着广泛的运用。压缩算法令系统更有效,成本更低。再来说密码学算法中非常重要的RSA算法,如果没有这些算法,互联网就会变得不安全,电子交易就不会如此可信。
好玩的算法还有很多很多,历法与二十四节气的计算、华容道、井字棋、黑白棋、五子棋以及俄罗斯方块……你会惊讶地发现,再简单不过的事情背后,都藏着算法的神奇背影。不妨将本书放在案头慢慢品读,你将能看到算法如何深入我们的日常生活,如何重塑我们的世界。
你准备好了吗?接下来,这个世界算法将接管一切。
啊哈磊
《啊哈!算法》作者
本书的序和部分试读章节可在CSDN的资源下载部分下载,以下是本书目录的三级标题展开: