玩转算法

学习算法太枯燥?那么就来“玩”算法吧

本文作者:图灵访谈 2015-10-14 17:20

导语:他说他是一个“玩”算法的人 —— 等等,算法有什么可玩的?

王晓华是一位热衷于算法研究的程序员,也是《算法的乐趣》一书的作者。他目前在中兴通讯上海研发中心从事光纤接入网通讯设备开发,担任EPON(以太网无源光网络)业务软件开发经理,参与开发的PON设备在全球部署过亿线,为数亿家庭提供宽带接入服务。

对于算法,王晓华更愿意称自己是在“玩”,“玩算法”最大的乐趣就是用程序解决生活中的问题。当年为了方便使用Visual Studio 6.0开发软件,他特意编写了一个tabbar插件,并随后开源了这个软件。为了文档安全,他开发了一个基于layerFSD技术的透明文件加密系统,在朋友圈内广为流传。后来他在使用Source Insight软件的时候,又以外挂的形式为Source Insight开发了TabSiPlus插件,受到了很多程序员朋友的欢迎。

关于算法该怎么“玩”,王晓华自有多年的经验分享:

为了玩游戏而开始的算法之旅

从上大学时候开始,我迷上了算法。那时候,像我这样的懒人觉得拼音输入法太繁琐,于是就去学“表形码”(当然,因为笨的原因,现在还在用拼音输入法)。资深一点的游戏玩家都还记得,那个时候为了玩中文DOS游戏,很多人都装了UCDOS中文环境,UCDOS没有表形码,但是支持通过码表文件增加自定义输入法。我研究了Windows上的表形码码表文件(老师给的,适用于Windows 3.x版本)和UCDOS码表文件的格式,发现二者有一定的相似性:都是文本文件,有固定的格式,每一行由一组编码和一个字或词组成一个编码对。二者的区别仅仅在于一个文件是编码在前,对应的字或词在后面,另一个刚好相反,字或词在前,对应的编码在后面。码表文件有十几万行,手工修改是不可能了,刚好当时在上C语言课,就决定写个程序来做这个事情。

神奇的表形码

第一次运行我写的程序,十几秒钟都没有结束。因为我之前写的C语言作业,从来没有哪个程序运行时间超过1秒钟的,所以我觉得这个程序挂了,于是我就“Ctrl+Break”了。但是分析代码又觉得没有问题,看了遗留在磁盘上的码表文件,发现转换了几千行,并且内容是对的。于是再次运行程序,等了2-3分钟,程序结束了。我急不可待地将得到的码表文件导入UCDOS,发现可以用,当时就感觉非常有成就感。这是我第一次为解决一个实际的问题编写算法,尽管当时还没有算法、软件的概念,但是隐隐约约就觉得这东西有用,不是只用于完成作业,还可以解决实际的问题。后来我接触到了更多的有用算法以及各种算法竞赛,一直到现在,写个程序解决问题几乎成了一种习惯。

学习算法难在哪里?

许多算法是有难度的,理论很复杂,不容易理解和掌握,这是客观存在的现实。但是我们可以通过提高自身分析问题和解决问题的能力来相对地降低学习难度。从基础来讲,要深入理解数据结构,至少要非常熟练地掌握一种排序算法,各种线性表的插入、删除算法,树的遍历和插入、删除算法,图的遍历算法等等。然后要多学习,掌握一些常见问题的解决模式,比如穷举算法如何应用,动态规划算法如何应用等等。最后要勤思考,对应已经掌握并解决的算法,要想想为什么用这种方法解决,有没有其他方法,类似的问题怎么办,提高举一反三的能力。

想学好计算机算法,数学问题是无法回避的。数学的重要性不在于算法中用了哪些公式或数学原理,其重要性在于一种思维方式的培养。当我们遇到一个新的问题的时候,通常有两种解决问题的方式,一种方式是创造一种新的方法来解决这个问题,另一种方式是将新问题分解、转化成已知问题,然后用已知的方法解决这个问题。这两种方式都很需要抽象思维能力,现实生活中很少有机会锻炼抽象思维能力,而学习数学是一种很好地培养这种能力的方法。但是并不是说要学好算法就必需成为数学大咖,而是通过学习数学促进抽象思维能力的提高。

算法设计又难在何处?

参加算法竞赛其实是一件很痛苦的事情,要经过大量的训练,很多人会选择背一些算法或整理一些算法模板,到时候可以直接套用。在理解算法的基础上熟记一些经典的算法实现其实也是一件无可厚非的事情,我上学的时候也参加过一些比赛,通常在比赛之前也会突击训练一两个月,背很多东西,基本上也是事后一个月就全忘了。

比赛的题目一般都有特定的套路,但是现实生活中的算法往往就事而论,有可能只有你遇到过,没有现成的经验,需要自己从无到有来解决问题。我认为算法设计有三个方面需要强调:模型的建立、演化算法和输入、输出的转换。这三个方面中模型的建立是关键,很多情况下,模型建好了,演化算法和输入、输出的转换就水到渠成。

建立模型的基础是数据结构。当一个问题的数据存在先进先出的特性时,你要想到队列。当一个问题的数据需要频繁查找操作时,你要想到有序表、hash、map。当一个问题的数据需要频繁的插入、删除操作时,你要想到链表。当一个问题中的数据包含父子关系时,你要想到树。当一个问题中的数据中既有节点又有路径什么的,你要想到图。这些都和使用数据结构的经验有关,只要多练习就能掌握。

建立模型还需要抽象的逻辑思维能力。简单地说,就是运用抽象的逻辑思维,抓住问题的主要因素,忽略次要因素,建立问题的框架。

算法设计之难体现在思维方式的转换和模型的建立。前面说过,这需要有抽象思维能力,缺乏这种能力,连问题都很难想明白,更不用说设计解决问题的算法了。幸运的是这种能力是可以培养的,学好数学,多研究一些算法,积累些经验,都是很好的提高抽象思维能力的方法。

算法学习的干货推荐

在我学习算法的过程中,兴趣是最大的推动力。兴趣来自于我觉得这东西能解决问题,对自己有用。我在策划《算法的乐趣》这本书的时候,我依然沿用了这种思想。我选取、介绍的例子都是大家生活中没有在意,但是却处处都会遇到的算法,通过这些例子让大家觉得算法是有用的,并通过这个来吸引大家关注算法,学习算法,从而达到提高能力的作用。

算法学习是一条并不简单的路,就我的经验而言,在计算机上学习算法首先需要熟悉编程语言和数据结构,关于编程语言和数据结构有很多经典的书籍,我就不多介绍了。就算法而言,我看过的书有Cormen的《算法导论》、Knuth的《计算机程序设计艺术》、Weiss的《数据结构与算法分析》、Levitin的《算法设计与分析基础》、Kleigberg的《算法设计》等等。想参加算法竞赛的同学可以参考刘汝佳等人编写的《算法艺术与信息学竞赛》,以及《ACM国际大学生程序设计竞赛题解》。因为时间过去太久了,已经不记得看这些书的顺序了,只记得最早看的是《算法导论》,关于顺序实在没有什么经验可谈。

至于如何读这些算法的经典书籍,我倒是有一些经验和大家分享:

不管哪一本书,都不要泛泛地看一遍就觉得看懂了,而是要把书中的每一个例子算法都用程序写出来,这样才能留下深刻的印象。如果遇到看不懂的地方,不要停下来,跳过去看其他算法,过几天在回头来看,如果还看不懂就再过几天再回头来看。千万不要在一个地方停下来,否则你很可能就此失去兴趣,恐怕永远也看不完这本书了。

此外,还有一些学习算法的网站值得推荐:

游戏开发相关的算法介绍:

http://www.gamedev.net

http://theory.stanford.edu/~amitp/GameProgramming

http://www.gamasutra.com

http://www.sudoku.com

俄罗斯方块游戏的算法网站:

http://gforge.inria.fr/projects/mdptetris

http://colinfahey.com/tetris/tetris.html

leetcode,最近很火的算法网站:

http://www.leetcode.com

Topcoder,也很经典,每周都有竞赛,有奖金的:

http://community.topcoder.com/tc

还有很多大学也有自己的竞赛题库,比如北大、杭电和华中科技大学等等。

编程算法、推荐算法、数据挖掘涉及的算法的区别和联系?

编程算法应该只是算法的一种表达形式,我们还可以用表格或流程图来表达算法。数据挖掘领域涉及的算法和其他领域的算法并无本质的区别,只是问题域不同。数据挖掘和机器学习常用的方法,比如决策树、贝叶斯学习、神经网络、遗传算法等等,在其他领域也都是有应用的。神经网络、遗传算法作为启发性搜索算法在人工智能和最优化求解领域也得到了广泛应用。贝叶斯学习在一些电子邮件应用程序中也有应用,主要用于垃圾邮件的识别。在人工智能领域或各种专家系统中,决策树算法也是常用算法。各种算法之间的联系还是很普遍的,在不同的领域扮演着不同的角色,本质上没有区别。

在日常生活中,我们有机会见到越来越多的推荐算法,我曾经想买一个佳能镜头,于是用了一下百度,想了解几种镜头的评价,结果一连几天,只要登录京东或淘宝,首页都会给我推荐与数码相机有关的配件或镜头信息。因为工作领域的原因,我对推荐算法没有深入的研究,我认为这种算法应该主要是建立在大数据上的数据分类、筛选和过滤。不过就我对算法的理解来说,目前的推荐算法还是有改进余地的,比如要能区分同一台计算机的不同使用者,不要在我用电脑的时候向我推荐女式内衣和化妆品,那是我老婆关注的东西。(笑)

生活中处处有算法

应该说,在我的工作和生活中也是处处都有算法。说到网络协议,TCP协议中的“滑动窗口算法”也是很经典的算法。路由器和交换机中为了避免出现端口环路,都会使用最小生成树算法。在接入网设备中,通常语音报文的优先级高于视频报文,视频报文的优先级又高于一般的数据报文,当一大波各种报文来临时,设备如何处理?这个算法也很经典,就是用多个队列加上一个调度算法,简单说就是六个字:分分类,排排队。

随着宽带的普及,现在几乎家家都有路由器,很多人都会在路由器上给各个端口配置带宽,这就会用到带宽分配算法,令牌算法和Max-Min Fairness带宽分配算法都是经典的带宽分配算法。网络传输的数据报文出了错码怎么办?那就要纠错,Reed-Solomon编码和解码算法就是这样的经典纠错算法,除此之外,Reed-Solomon编码和解码算法还用于光盘、磁盘的数据纠错。

说实话,我曾经“玩”过的算法,绝大多数都没有机会直接应用到工作当中,但是“玩”算法对我的影响是显而易见的,它提高了我的动手能力,以及遇到问题时分析并解决问题能力,这就是收获,也是任何一个软件企业对程序员最基本的要求。

雷锋网原创文章,未经授权禁止转载。详情见转载须知

时间: 2024-10-12 22:28:32

玩转算法的相关文章

算法面试课程笔记000 玩转算法面试 leetcode题库分门别类详细解析

算法面试课程笔记 =============================================================================== 本文地址 : =============================================================================== liuyubobobo老师 <<玩转算法面试 leetcode题库分门别类详细解析>> 为了面试,更为了提升你的算法思维 http:/

玩转算法系列--图论精讲 面试升职必备(Java版)

第1章 和bobo老师一起,玩转图论算法欢迎大家来到我的新课程:<玩转图论算法>.在这个课程中,我们将一起完整学习图论领域的经典算法,培养大家的图论建模能力.通过这个课程的学习,你将能够真正地,玩转图论算法:) 第2章 图的基本表示千里之行,驶于足下.解决任何有一个图论算法问题,首先需要用基本的数据结构来表示图.在这一章,我们就将探索图的基本表示问题,学习邻接矩阵和邻接表,进而,也让同学们熟悉这个课程的整体代码风格. 第3章 图的深度优先遍历任何一种数据结构,都需要进行遍历.图也不例外.通过深

韩顺平_PHP程序员玩转算法公开课(第一季)01_算法重要性_五子棋算法_汉诺塔_回溯算法_学习笔记_源代码图解_PPT文档整理

文西马龙:http://blog.csdn.net/wenximalong/ 课程说明:算法是程序的灵魂,为什么有些网站能够在高并发,和海量吞吐情况下依然坚如磐石,大家可能会说: 网站使用了服务器集群技术.数据库读写分离和缓存技术(比如memcahced和redis等),那如果我再深入的问一句,这些优化技术又是怎样被那些天才的技术高手设计出来的呢? 我在上大学的时候就在想,究竟是什么让不同的人写出的代码从功能看是一样的,但从运行效率上却有天壤之别, 就拿以前在软件公司工作的实际经历来说吧, 我是

韩顺平_PHP程序员玩转算法公开课(第一季)02_单链表在内存中存在形式剖析_学习笔记_源代码图解_PPT文档整理

文西马龙:http://blog.csdn.net/wenximalong/链表——最灵活的数据结构链表用来解决复杂的问题和算法是很方便的. 内容介绍1.什么是链表2.单向链表3.双向链表4.环形链表5.使用环形链表解决约瑟夫问题 链表——什么是链表链表是有序的列表,但是它在内存中是分散存储的. 链表无处不在,比如在操作系统中,文件和文件之间,文件块和文件块之间,是靠链表链接起来的.使用链表可以解决类似约瑟夫问题,排序,索引,二叉树,广义表... 链表——单链表的快速入门使用head头的单向链表

玩转算法面试 从真题到思维全面提升算法思维

第1章 算法面试到底是什么鬼?一提起算法面试,很多同学就会心有余悸.可其实,大多数企业的算法面试,并没有那么可怕.并不是一定要啃完整本<算法导论>,才能玩儿转算法面试:也并不是只有ACM参赛选手,才能笑傲算法面试.恰恰相反,大多数算法面试关注的算法思维,其实很基础.在这一章,和大家聊一聊,算法面试,到底是什么鬼?... 第2章 面试中的复杂度分析很多同学一提起复杂度分析就头疼,马上想起了<算法导论>中复杂的数学推导.但其实在一般的企业面试中,对复杂度的分析要求并没有那么高,但也是绕

玩转算法面试 互联网公司真题【完整版】

 下载地址:http://feixueteam.net/thread-1166-1-1.html

图灵书单——程序员的算法

小编跟着图灵听课去(4月)参加了很多线下的会议,再次深深体会到算法很重要,因为不管是什么技术主题的大会,人们都会找算法的书.现在小编就来盘点一下图灵新出版的算法书,推荐给大家. 1.<程序员的数学>第3弹--线性代数 作者:[日] 平岡和幸,[日] 堀玄 译者:卢晓南 定价:79 页数:384 ● 机器学习.数据挖掘.模式识别必备基础知识 ● 从入门到应用,透彻理解线性代数的本质 <程序员的数学3:线性代数>沿袭"程序员的数学"系列平易近人的风格,用通俗的语言和

常见算法题合辑(一)

这一章的内容,有些之前已经在微信公众号中将详细的思路及步骤汇总过,有些之后可能会再找时间对其进行分析,这里只将最终实现罗列出来,难易程度不分先后,算法复杂度不保证是最优,留给大家空间自行思考,当然,本章用的是C#语言进行编码,大家可以使用自己熟悉的语言将这些算法实现一遍哦~ 如果你有什么有趣的算法题或者没能解决的算法题,也可以留言给小编,让我们一起玩转算法~ 1. 冒泡排序 这个算是所有算法中最为简单的了,实现方法如下: 2. 插入排序 从排序算法来看,这个算法也是属于比较简单的了,实现方法如下

Python3入门机器学习 经典算法与应用

详情请交流  QQ  709639943 00.Python3入门机器学习 经典算法与应用 00.老司机学python篇:第一季(基础速过.机器学习入门) 00.Python 从入门到精通 78节.2000多分钟.36小时的高质量.精品.1080P高清视频教程!包括标准库.socket网络编程.多线程.多进程和协程. 00.Django实战之用户认证系统 00.Django实战之企业级博客 00.深入浅出Netty源码剖析 00.NIO+Netty5各种RPC架构实战演练 00.JMeter 深