{ZZ}知其所以然地学习(以算法学习为例)

42 views
Skip to first unread message

pongba

unread,
Jul 7, 2008, 8:14:46 AM7/7/08
to TopLanguage

以web方式浏览该页面的同学请点击(groups不支持图片显示):http://blog.csdn.net/pongba/archive/2008/07/07/2622713.aspx

以邮件接收的同学应该没问题:)

知其所以然地学习(以算法学习为例)

 

By 刘未鹏(pongba)

C++的罗浮宫(http://blog.csdn.net/pongba)

 

其实下文的绝大部分内容对所有学习都是同理的。只不过最近在正儿巴经地学算法,而后者又不是好啃的骨头,所以平时思考总结得就自然要比学其它东西要多一些。

问题:目前几乎所有的算法书的讲解方式都是欧几里德式的、瀑布式的、自上而下的、每一个推导步骤都是精准制导直接面向目标的。由因到果,定义、引理、定理、证明一样不少,井井有条一丝不乱毫无赘肉。而实际上,这完全把人类大脑创造发明的步骤给反过来了。看起来是阳关大道,实际上车马不通。

而对读者来说,这就等于直接告诉你答案&做法了,然后让你去验证这个答案&做法是可行&成立的。而关于答案&做法到底是怎么来的,从问题到答案之间经历了怎样的思维过程。却鲜有书能够很好的阐释。就我有限的阅(算法)书经验,除了波利亚的《怎样解题》还算合格之外(也并非最理想),其它的(包括有名的《算法导论》、《如何解题:现代启发式方法》、TAOCP、《Algorithms》、《编程珠玑》etc.),都远远算不上合格,为什么我这么说呢,因为我发现每每需要寻找对一个算法的解释的时候,翻开这些书,总是直接就看到关于算法逻辑的描述,却看不到整个算法的诞生过程背后的思想。

我们要的不是相对论,而是诞生相对论的那个大脑。我们要的不是金蛋,而是下金蛋的那只鸡。

为什么会这样,其实是有原因的。

我们在思考一个问题的过程中有两种思维形式:

  • 联想:这种思维某种程度上可以说是"混乱"的(虽然从一个更根本的层面上说是有规则的),所谓混乱是指很多时候并不确定联想到的做法最终是否可行,这些联想也许只是基于题目中的某个词语、语法结构、问题的某个切片、一些零星局部的信息。这个过程是试探性的。最后也许有很大一部分被证明是不可行的。很多时候我们解决问题用的都是这种思维,简言之就是首先枚举你关于这个问题能够想到的所有你学过的知识,然后一一往上套看看能否解决手头的问题。这种思维方式受限于人脑联想能力本身的局限性。我在《跟波利亚学解题》中就提到了几个例子。联想本身需要记忆提取的线索,所以受到记忆提取线索的制约,如果线索不足,那怎么也联想不起来。而提取线索的建立又取决于当初保存记忆的时候的加工方法(《找寻逝去的自我》里面有阐述),同时,面对一个问题,你能够从中抽取出来的联想线索又取决于你对问题的认识层度/抽象深度,表浅的线索很可能是无关的,导致无效的联想&试错(《Psychology of Problem Solving》里面有阐述)。总之,联想这个过程充满了错误的可能。
  • 绎&归纳:演绎&归纳是另一种思维形式。它们远比联想有根据。其中演绎是严格的,必然的。归纳也是有一定根据的。在面对一个问题的时候,我们有意无意的对问题中的各个条件进行着演绎;譬如福尔摩斯著名的"狗叫"推理——狗+生人=>吠叫 & 昨晚狗没有叫 => 那个人是熟人。就是一个典型的对问题的各个条件进行演绎的推理过程。还有就是通过对一些特殊形式的观察来进行归纳,试图总结问题中的规律。然而,不幸的是,面对复杂的问题,演绎&归纳也并不总是"直奔"问题的解决方案的。人的思维毕竟只能一下子看到有限的几步逻辑结论,一条逻辑演绎路径是否直奔答案,不走到最后往往是不知道的,只要答案还未出现,我们大脑中的逻辑演绎之树的末端就始终隐藏在黑暗之中。而当最终答案出现了之后,我们会发现,这棵演绎之树的很多分支实际上都并不通往答案。所以,虽然演绎&归纳是一种"必然"的推理,然而却并不"必然"引向问题的结论,它也是试错的,只不过比联想要更为靠谱一些。

既然认识到,人类解决问题的两大思维方式实际上都是有很大的试错成分的(好听一点叫"探索"),那么就不难意识到,对一个问题的思考过程实际上是相当错综复杂的,而且充满了无效分支——在思考的过程中我们也会不断的对分支进行评估,做适当的剪枝——因此当我们找到问题的解之后,一来思维的漫长繁杂的过程已经在大脑里面淡化得差不多了,只有那些引向最终结论的过程会被加"高亮"——我们在思考的过程中本就会不断的抛弃无效的思路,只留下最有希望的思路。简而言之就是最后证明没用或者早先我们就不抱希望的一些想法就被从工作记忆中扔掉了。二来,思考过程是我们的空气和水,而"鱼是最后一个感觉到水的",我们感觉不到思维法则本身的存在,我们只是不知不觉运用它。三来,由于我们的目标是问题的解,解才是我们为之兴奋和狂喜的东西,而不是求解的过程,过程只是过程,目的才是目的。这就像一个寻宝者,在漫长曲折的寻宝历程之后,在找到宝藏的时候,他会对宝藏感到狂喜(记得阿基米德的"找到了!"吗?)而迫不及待地要展示出来,而漫长的思考本身却成了注脚。我们是有目的的动物,目的达到了,其它的就相对不那么重要了。最后,对于传授知识的人,也许还有其四:感到介绍思维过程是不相干的,毕竟思维过程并不是算法问题的解,算法问题的解才是算法问题的解。然而不幸的是,忽视到达解的那个过程实际上却变成了舍本逐末。我们看到的是寥寥数行精妙绝伦的算法,然后仰天长叹自己想不出来啊想不出来。为什么想不出来,因为你不知道那短短数行算法背后经历的事怎样漫长的思考过程,如果问题求解是一部侦探小说,那么算法只是结局而已,而思考过程才是情节

既然如此,也就难怪古往今来算法牛人们算法牛,但却没有几个能真正在讲述的时候还原自己的思维过程的(那个" 渔"字),手把手的教学生走一遍推理的思路,就可以让学生获得思维过程的训练。金出武雄在《像外行一样思考,像专家一样实践》中说写论文应该写得像侦探小说一样,我很赞同。欧几里德式的介绍,除了提供枯燥的知识之外,并没有提供帮助人获得知识的东西——思维(关于对数学书籍的欧几里德式写法的批评其实也是由来已久了,并且有人呼吁了好几种其它的教学方法)。从这方面,我们所尊敬的一些"圣经"级书籍在传道授业上还不如侦探小说,前者是罗列一大堆知识,后者则是阐述获得知识的过程——推理&联想。

然而,我们都是人,人类该有的思维形式,我们难道不是都有吗。既然如此,思维本身又有什么需要一遍遍教的呢?

并非如此。

讲述思维过程而非结果有几个极其重要的价值:

  • 内隐化:思维法则其实也是知识(只不过它是元知识——是帮助我们获得新知识的知识);是内隐的记忆。我们在思考的过程中觉察不到思维法则的作用,它们却在幕后实实在在的左右着我们的思维轨迹。要将思维方法内隐化,需要不断练习,就像需要不断练习才能无意识状态下就能骑自行车一样。
  • 跨情境运用:思维法则也是知识记忆,是问题解决策略。既然是记忆,就受到提取线索的制约,这就是为什么当波利亚告诉你要"注意未知数"之后你还是不能真正在所有需要你"注意未知数"的地方都能提醒自己"注意未知数"。很多时候未知数是很隐蔽的,未知数并不会总是头顶一个大帽子上面写着"我是未知数"。所以很多时候缺乏对这个策略的"提醒"线索,这也是为什么你学会了在解决数学问题的时候"注意未知数"却不一定能在解决现实生活中的问题中时刻都能"注意你的未知数"《你的灯亮着吗?》整本书的价值便在于此),因为解数学题和解决生活中问题的场景不一样,不同的环境线索,在你大脑中激发的记忆也不一样。就连问题求解中,不同的问题之间的细小差别也可能导致思维轨迹很大的不同,有时你的注意力会被一个无关线索激发的联想吸引开去,忘记如"注意你的未知数"这样的重要法则。而一本从思维角度来讲问题求解的书则可以一遍遍将你置于不同的问题场景下然后在该提醒你的时候提醒你,让你醒悟到"哦,原来这个时候也应该想到这个啊。",做多了这样的思维演习你就会逐渐从中领悟到某种共性,并将一些思维习惯得到强化,于是终于能够在需要运用某策略的时候能适时的想起来了。
  • 对问题解的更多记忆提取线索:我们平时学习算法时几乎仅止于"理解",别人把一个方案放在你面前,你去验证一下,心说"哦,不错,这个的确可以工作"。然后就没了。稍微简单一点的算法还好,复杂一点的对于记忆的负担是很大的,这就是为什么有时候我们看到一个绝妙的解法,这个解法看上去不知道从哪里来的,但经过我们的理解,却发现是对的,我们感叹,真巧妙,结果一些天之后,别人问起这个问题,我们说:"唉,那是个多么巧妙的算法啊,但是我只记得它巧妙,却不记得它到底是怎样的了。" 为什么?因为在不知其所以然的情况下,算法只是一堆离散的机械步骤,缺少背后的思想的支撑,这些步骤之间就没有一个本质层面上的关联(先知亚里士多德早就指出:学习即联接)。所以就跟背历史书也没多大区别。然而,知道了算法是怎样一步步被推导出来的,我们就一下拥有了大量的记忆提取线索:对算法发现过程中的任何一个关键步骤(尤其是本质)的回忆都可能使我们能够自己动手推导出剩余的内容譬如你知道堆(heap)是怎样由朴素的决策树演化而来的,它又是为了解决什么问题的,你即便忘记了具体的细节,也可以自己推导出来。譬如你知道KMP算法的本质在于消除回溯,至于如何消除回溯却并不是那么难以推导的,所以即便忘了也可以借助于大脑的逻辑演绎能力再现出来。譬如你知道Tarjan算法其实只是从后序遍历经过两个优化调整而来的(其中并査集的使用其实只是优化手段——为了能够迅速判断祖先节点是谁——而非算法本质——当然,算法设计的主要任务本来就是通过问题条件中蕴含的知识来"消除冗余计算"和"避免不必要计算",所以你也可以说并査集的使用是关乎本质的,只不过,知道了为什么需要引入并査集,就会强烈地感觉到一切是顺理成章的了),那这个出了名的绕人的算法也就不那么难以理解和记忆了。譬如你知道排序的本质,就能够对什么是最优排序,为什么它是最优排序有深刻的认识。四两拨千斤。

       

  • 包含了多得多的知识记一个算法,就只有一个算法。一个萝卜一个坑。就好比背99乘法表只能解决乘法问题一样。而记背后的思想,却有助于解决一类问题。思想所处的抽象层面往往比到处都是实现细节的算法本身要低,越是低的抽象层次,越是本质,涵盖范围越是广泛。数学的发展本身就体现了这个过程,抽象代数就是非常好的例子。算法诞生过程中的思路往往包含了比实际算法更本质得多的知识,实际算法乃至算法的某个特定语言的实现包含了太多表面的不相干知识,它们会阻碍对本质的理解。
  • 重在分析推理,而不是联想:学了一大通算法和数据结构之后的一个副作用就是,看到一个问题之后,脑袋里立即不管三七二十一冒出一堆可能相干的数据结构和算法来。联想是强大的思维捷径,在任何时候都会抢占大脑的工作记忆,由不得你控制——比如我问你"如何寻找区间的最大值",首先进入你的意识的肯定就是学过的那个算法,甚至算法的实现细节都一一跳了出来,也许最先跳出来的还是算法实现中某个最容易弄错的边界细节,或是某个比较tricky的实现技巧!然而这些其实根本不反映一个算法的本质,结果想来想去总是停留在问题的表层。而另一方面,重在思维的传授则可以让人养成从问题本质入手,逐步分析推理的习惯,而不是直接生搬硬套。当然,联想本身也是极其重要的思维方法,甚至可以说是人类思维的"唯一"的特征。很多时候我们并不知道问题的本质是什么,需要靠联想来领路。只不过,养成从问题的本质入手的好习惯绝对是有更大的好处的。

那到底什么样的才算是授人以渔的呢?波利亚的《如何解题》绝对算是一本,他的《数学的发现》也值得一看。具体到算法书,那就不是光看text book就足够的了,为了深入理解一个算法的来龙去脉前因后果,从一个算法中领悟尽量深刻的东西,则需要做到三件事情:

  • 寻找该算法的原始出处:TAOCP虽然本身在算法思维的传授方面做得不好,但作为一个资料库是绝对优秀的,基础的算法只要你能想到的,几乎都可以在上面找到原始出处。查到原始出处之后(譬如一篇paper),就可以去网上搜来看了。
  • 原始的出处其实也未必就推心置腹地和你讲得那么到位,前面说过,算法设计出来了之后人们几乎是不会去回顾整个的思维过程细节的,只把直指目标的那些东西写出来。结果就又是一篇欧几里德式的文章了。于是你就迷失在一大堆"定义"、"引理"、"定理"之中了。这种文章看上去整个写得井井有条,其实是把发明的过程整个给颠倒过来了,我一直就想,如果作者们能够将整个的思路过程写出来,哪怕文字多上十倍,我也绝对会比看那一堆定义定理要容易理解得多。话说回来,怎么办?实在找不出好的介绍,只能自己揣摩了。揣摩的重要性,是怎么说都不为过的。揣摩的一些指导性的问题有:为什么要这样(为什么这是好的)?为什么不是那样(有其它做法吗?有更好的做法吗?)?这样做是最好的吗?(为什么?能证明吗?)这个做法跟其它的什么做法有本质联系吗?这个这个的区别是什么?问题的本质是什么这个做法的本质又是什么?到底本质上是什么东西导致了这个做法如此..?与这个问题类似的还有其它问题吗?(同样或类似的做法也适用吗?)等等。
  • 不仅学习别人的思路,整理自己的思路也是极其重要的。详见《跟波利亚学解题》的"4. 一个好习惯"和"7. 总结的意义"。

前一段时间我们讨论组上有不少例子,见这里,或这里

(完)



--
刘未鹏(pongba)|C++的罗浮宫
http://blog.csdn.net/pongba
TopLanguage
http://groups.google.com/group/pongba

Eric

unread,
Jul 7, 2008, 9:48:58 AM7/7/08
to TopLanguage
其他我不敢说,TAOCP 绝对是启发式的。只有证明是公理式的。

On 7月7日, 上午7时14分, pongba <pon...@gmail.com> wrote:
> 以web方式浏览该页面的同学请点击(groups不支持图片显示):http://blog.csdn.net/pongba/archive/2008/07/07/2622713.aspx
>
> 以邮件接收的同学应该没问题:)
>
> 知其所以然地学习(以算法学习为例)
>
> By 刘未鹏(pongba)
>
> C++的罗浮宫(http://blog.csdn.net/pongba)
>
> 其实下文的绝大部分内容对所有学习都是同理的。只不过最近在正儿巴经地<http://blog.csdn.net/pongba/archive/2008/06/05/2513263.aspx>
> 学算法,而后者又不是好啃的骨头,所以平时思考总结得就自然要比学其它东西要多一些。
>
> 问题:目前几乎所有的算法书的讲解方式都是欧几里德式的、瀑布式的、自上而下的、每一个推导步骤都是精准制导直接面向目标的。由因到果,定义、引理、定理、证明-一样不少,井井有条一丝不乱毫无赘肉。而实际上,这完全把人类大脑创造发明的步骤给反过来了。看起来是阳关大道,实际上车马不通。
>
> 而对读者来说,这就*等于直接告诉你答案&做法了*,然后*让你去验证*
> 这个答案&做法是可行&成立的。而关于答案&做法到底是怎么来的,从问题到答案之间经历了怎样的思维过程。却鲜有书能够很好的阐释。就我有限的阅(算法)书经验-,除了波利亚的《怎样解题》还算合格之外(也并非最理想),其它的(包括有名的《算法导论》、《如何解题:现代启发式方法》、TAOCP、《Algorithm-s》、《编程珠玑》etc.),都远远算不上合格,为什么我这么说呢,因为我发现每每需要寻找对一个算法的解释的时候,翻开这些书,总是直接就看到关于算法逻辑-的描述,却看不到整个算法的诞生过程背后的思想。
>
> *我们要的不是相对论,而是诞生相对论的那个大脑。我们要的不是金蛋,而是下金蛋的那只鸡。*
>
> 为什么会这样,其实是有原因的。
>
> 我们在思考一个问题的过程中有两种思维形式:
>
> - *联想*
> :这种思维某种程度上可以说是"混乱"的(虽然从一个更根本的层面上说是有规则的),所谓混乱是指很多时候并不确定联想到的做法最终是否可行,这些联想也许只是-基于题目中的某个词语、语法结构、问题的某个切片、一些零星局部的信息。这个过程是试探性的。最后也许有很大一部分被证明是不可行的。很多时候我们解决问题用的-都是这种思维,简言之就是首先枚举你关于这个问题能够想到的所有你学过的知识,然后一一往上套看看能否解决手头的问题。这种思维方式受限于人脑联想能力本身的局-限性。我在
> 《跟波利亚学解题》 <http://blog.csdn.net/pongba/archive/2008/04/18/2302905.aspx>
> 中就提到了几个例子。联想本身需要记忆提取的线索,所以受到记忆提取线索的制约,如果线索不足,那怎么也联想不起来。而提取线索的建立又取决于当初保存记忆的时-候的加工方法(
> 《找寻逝去的自我》 <http://www.douban.com/subject/1315575/>
> 里面有阐述),同时,面对一个问题,你能够从中抽取出来的联想线索又取决于你对问题的认识层度/抽象深度,表浅的线索很可能是无关的,导致无效的联想&试错(《-Psychology
> of Problem Solving》
> <http://www.douban.com/subject/2845839/>里面有阐述)。总之,联想这个过程充满了错误的可能。
>
> - *演**绎&归纳*:演绎&归纳是另一种思维形式。它们远比联想有根据。其中演绎是严格的,必然的。归纳也是有一定根据的。在面对一个问题的时候,我们有意无意-的对问题中的各个条件进行着演绎;譬如福尔摩斯著名的"狗叫"推理----狗+生人=>吠叫
> & 昨晚狗没有叫 =>
> 那个人是熟人。就是一个典型的对问题的各个条件进行演绎的推理过程。还有就是通过对一些特殊形式的观察来进行归纳,试图总结问题中的规律。然而,不幸的是,面对-复杂的问题,演绎&归纳也并不总是"直奔"问题的解决方案的。人的思维毕竟只能一下子看到有限的几步逻辑结论,一条逻辑演绎路径是否直奔答案,不走到最后往往是-不知道的,只要答案还未出现,我们大脑中的逻辑演绎之树的末端就始终隐藏在黑暗之中。而当最终答案出现了之后,我们会发现,这棵演绎之树的很多分支实际上都并不-通往答案。所以,虽然演绎&归纳是一种"必然"的推理,然而却并不"必然"引向问题的结论,它也是试错的,只不过比联想要更为靠谱一些。
>
> 既然认识到,*人类解决问题的两大思维方式实际上都是有很大的试错成分的*
> (好听一点叫"探索"),那么就不难意识到,对一个问题的思考过程实际上是相当错综复杂的,而且*充满了无效分支*
> ----在思考的过程中我们也会不断的对分支进行评估,做适当的剪枝----因此当我们找到问题的解之后,*一来思维的漫长繁杂的过程已经在大脑里面淡化得差不多了*
> ,只有那些引向最终结论的过程会被加"高亮"----我们在思考的过程中本就会不断的抛弃无效的思路,只留下最有希望的思路。简而言之就是最后证明没用或者早先我们-就不抱希望的一些想法就被从工作记忆中扔掉了。
> *二来,思考过程是我们的空气和水,而"鱼是最后一个感觉到水的<http://blog.csdn.net/pongba/archive/2008/01/04/2025830.aspx>
> "*,我们感觉不到思维法则本身的存在,我们只是不知不觉运用它。*三来,由于我们的目标是问题的解*,解才是我们为之兴奋和狂喜的东西,而不是求解的过程,*
> 过程只是过程,目的才是目的*
> 。这就像一个寻宝者,在漫长曲折的寻宝历程之后,在找到宝藏的时候,他会对宝藏感到狂喜(记得阿基米德的"找到了!"吗?)而迫不及待地要展示出来,而漫长的思-考本身却成了注脚。我们是有目的的动物,目的达到了,其它的就相对不那么重要了。最后,对于传授知识的人,也许还有
> *其四:感到介绍思维过程是不相干的*
> ,毕竟思维过程并不是算法问题的解,算法问题的解才是算法问题的解。然而不幸的是,忽视到达解的那个过程实际上却变成了舍本逐末。我们看到的是寥寥数行精妙绝伦-的算法,然后仰天长叹自己想不出来啊想不出来。为什么想不出来,因为你不知道那短短数行算法背后经历的事怎样漫长的思考过程,如果问题求解是一部侦探小说,
> *那么算法只是结局而已,而**思考过程<http://blog.csdn.net/pongba/archive/2008/05/07/2412144.aspx>
> **才是情节*。
>
> 既然如此,也就难怪古往今来算法牛人们算法牛,但却没有几个能真正在讲述的时候还原自己的思维过程的(那个"
> 渔"字),手把手的教学生走一遍推理的思路,就可以让学生获得思维过程的训练。金出武雄在《像外行一样思考,像专家一样实践》<http://www.douban.com/subject/1867455/>
> 中说*写论文应该写得像侦探小说一样*
> ,我很赞同。欧几里德式的介绍,除了提供枯燥的知识之外,并没有提供帮助人获得知识的东西----思维(关于对数学书籍的欧几里德式写法的批评其实也是由来已久了,-并且有人呼吁了好几种其它的
> 教学方法 <http://en.wikipedia.org/wiki/Mathematics_education#Methods>)。*
> 从这方面,我们所尊敬的一些"圣经"级书籍在传道授业上还不如侦探小说*,前者是罗列一大堆知识,后者则是阐述获得知识的过程----推理&联想。
>
> 然而,我们都是人,人类该有的思维形式,我们难道不是都有吗。既然如此,思维本身又有什么需要一遍遍教的呢?
>
> 并非如此。
>
> 讲述思维过程而非结果有几个极其重要的价值:
>
> - *内隐化*:思维法则其实也是知识(只不过它是元知识----是帮助我们获得新知识的知识);是内隐的记忆<http://en.wikipedia.org/wiki/Implicit_memory>
> 。我们在思考的过程中觉察不到思维法则的作用,它们却在幕后实实在在的左右着我们的思维轨迹。要将思维方法内隐化,需要不断练习<http://blog.csdn.net/pongba/archive/2008/06/05/2513263.aspx>
> ,就像需要不断练习才能无意识状态下就能骑自行车一样。
> - *跨情境运用*:思维法则也是知识记忆,是问题解决策略。既然是记忆,就受到提取线索的制约,这就是为什么当波利亚告诉你<http://www.douban.com/subject/1456890/>
> 要"注意未知数"之后你还是不能真正在所有需要你"注意未知数"的地方都能提醒自己"注意未知数"。很多时候未知数是很隐蔽的,未知数并不会总是头顶一个大帽子-上面写着"我是未知数"。所以很多时候缺乏对这个策略的"提醒"线索,这也是为什么
> *你学会了在解决数学问题的时候"注意未知数"却不一定能在解决现实生活中的问题中时刻都能"注意你的未知数"*(《你的灯亮着吗?》<http://www.douban.com/subject/1135754/>
> 整本书的价值便在于此),因为解数学题和解决生活中问题的场景不一样,不同的环境线索,在你大脑中激发的记忆也不一样。就连问题求解中,不同的问题之间的细小差-别也可能导致思维轨迹很大的不同,有时你的注意力会被一个无关线索激发的联想吸引开去,忘记如"注意你的未知数"这样的重要法则。而一本从思维角度来讲问题求解-的书则可以一遍遍将你置于不同的问题场景下然后在该提醒你的时候提醒你,让你醒悟到"
> *哦,原来这个时候也应该想到这个啊。*
> ",做多了这样的思维演习你就会逐渐从中领悟到某种共性,并将一些思维习惯得到强化,于是终于能够在需要运用某策略的时候能适时的想起来了。
> - *对问题解的更多记忆提取线索<http://blog.csdn.net/pongba/archive/2008/06/05/2513263.aspx>
> *
> :我们平时学习算法时几乎仅止于"理解",别人把一个方案放在你面前,你去验证一下,心说"哦,不错,这个的确可以工作"。然后就没了。稍微简单一点的算法还好-,复杂一点的对于记忆的负担是很大的,这就是为什么有时候我们看到一个绝妙的解法,这个解法看上去不知道从哪里来的,但经过我们的理解,却发现是对的,我们感叹-,真巧妙,结果一些天之后,别人问起这个问题,我们说:"
> *唉,那是个多么巧妙的算法啊,但是我只记得它巧妙,却不记得它到底是怎样的了。*"
> 为什么?因为在不知其所以然的情况下,算法只是一堆离散的机械步骤,缺少背后的思想的支撑,这些步骤之间就没有一个*本质层面上的关联*
> (先知亚里士多德早就指出:学习即联接)。所以就跟背历史书也没多大区别。然而,*
> 知道了算法是怎样一步步被推导出来的,我们就一下拥有了大量的记忆提取线索:对算法发现过程中的任何一个关键步骤(尤其是本质)的回忆都可能使我们能够自己动手-推导出剩余的内容
> *。*譬如*你知道堆(heap)是怎样由朴素的决策树演化而来的,它又是为了解决什么问题的,你即便忘记了具体的细节,也可以自己推导出来。*譬如*
> 你知道KMP算法的本质在于消除回溯,至于如何消除回溯却并不是那么难以推导的,所以即便忘了也可以借助于大脑的逻辑演绎能力再现出来。*譬如*
> 你知道Tarjan算法其实只是从后序遍历经过两个优化调整而来的(其中并査集的使用其实只是优化手段----为了能够迅速判断祖先节点是谁----而非算法本质----当-然,算法设计的主要任务本来就是通过问题条件中蕴含的知识来"消除冗余计算"和"避免不必要计算",所以你也可以说并査集的使用是关乎本质的,只不过,知道了为-什么需要引入并査集,就会强烈地感觉到一切是顺理成章的了),那这个出了名的绕人的算法也就不那么难以理解和记忆了。
> *譬如*你知道排序的本质<http://blog.csdn.net/pongba/archive/2008/06/13/2544933.aspx>
> ,就能够对什么是最优排序,为什么它是最优排序有深刻的认识。四两拨千斤。
>
> - *包含了多得多的知识*:*记一个算法,就只有一个算法*。一个萝卜一个坑。*就好比背99乘法表只能解决乘法问题一样*。而记*
> 背后的思想,却有助于解决一类问题*
> 。思想所处的抽象层面往往比到处都是实现细节的算法本身要低,越是低的抽象层次,越是本质,涵盖范围越是广泛。数学的发展本身就体现了这个过程,抽象代数就是非-常好的例子。
> *算法诞生过程中的思路往往包含了比实际算法更本质得多的知识*
> ,实际算法乃至算法的某个特定语言的实现包含了太多表面的不相干知识,它们会阻碍对本质的理解。
> - *重在分析推理,而不是联想*:学了一大通算法和数据结构之后的一个*副作用*
> 就是,看到一个问题之后,脑袋里立即不管三七二十一冒出一堆可能相干的数据结构和算法来。联想是强大的思维捷径<http://www.douban.com/doulist/127649/>
> ,在任何时候都会抢占<http://en.wikipedia.org/wiki/Attention#Neural_correlates_of_attention>
> 大脑的工作记忆 <http://en.wikipedia.org/wiki/Working_memory>
> ,由不得你控制----比如我问你"如何寻找区间的最大值",首先进入你的意识的肯定就是学过的那个算法,甚至算法的实现细节都一一跳了出来,也许最先跳出来的还是-算法实现中某个最容易弄错的边界细节,或是某个比较tricky的实现技巧!然而这些其实根本不反映一个算法的本质,结果想来想去总是停留在问题的表层。而另一-方面,重在思维的传授则可以让人养成从问题本质入手,逐步分析推理的习惯,而不是直接生搬硬套。当然,联想本身也是极其重要的思维方法,甚至可以说是人类思维的-"
> 唯一 <http://en.wikipedia.org/wiki/Hebbian_learning>
> "的特征。很多时候我们并不知道问题的本质是什么,需要靠联想来领路。只不过,养成从问题的本质入手的好习惯绝对是有更大的好处的。
>
> 那到底什么样的才算是授人以渔的呢?波利亚的《如何解题》绝对算是一本,他的《数学的发现》也值得一看。具体到算法书,那就不是光看text
> book就足够的了,为了深入理解一个算法的来龙去脉前因后果,从一个算法中领悟尽量深刻的东西,则需要做到三件事情:
>
> - *寻找该算法的原始出处*
> :TAOCP虽然本身在算法思维的传授方面做得不好,但作为一个资料库是绝对优秀的,基础的算法只要你能想到的,几乎都可以在上面找到原始出处。查到原始出处之-后(譬如一篇paper),就可以去网上搜来看了。
> -
> 原始的出处其实也未必就推心置腹地和你讲得那么到位,前面说过,算法设计出来了之后人们几乎是不会去回顾整个的思维过程细节的,只把直指目标的那些东西写出来。-结果就又是一篇欧几里德式的文章了。于是你就迷失在一大堆"定义"、"引理"、"定理"之中了。这种文章看上去整个写得井井有条,其实是把发明的过程整个给颠倒-过来了,我一直就想,如果作者们能够将整个的思路过程写出来,哪怕文字多上十倍,我也绝对会比看那一堆定义定理要容易理解得多。话说回来,怎么办?实在找不出好-的介绍,只能自己
> *揣摩*了。*揣摩*的重要性,是怎么说都不为过的。揣摩的*一些指导性的问题有*
> :为什么要这样(为什么这是好的)?为什么不是那样(有其它做法吗?有更好的做法吗?)?这样做是最好的吗?(为什么?能证明吗?)这个做法跟其它的什么做法有-本质联系吗?
> *这个*跟*这个*的区别是什么?*问题的本质是什么*?*这个做法的本质又是什么*
> ?到底本质上是什么东西导致了这个做法如此..?与这个问题类似的还有其它问题吗?(同样或类似的做法也适用吗?)等等。
> - 不仅学习别人的思路,整理自己的思路也是极其重要的。详见《跟波利亚学解题》<http://blog.csdn.net/pongba/archive/2008/04/18/2302905.aspx>的"4.
> 一个好习惯"和"7. 总结的意义"。
>
> 前一段时间我们讨论组上有不少例子,见这里<http://groups.google.com/group/pongba/web/toplang-problemsolvingseries>
> ,或这里 <http://del.icio.us/pongbablog/%E8%A7%A3%E9%A2%98>。
>
> (完)
>
> --
> 刘未鹏(pongba)|C++的罗浮宫http://blog.csdn.net/pongba
> TopLanguagehttp://groups.google.com/group/pongba

pongba

unread,
Jul 7, 2008, 9:53:00 AM7/7/08
to pon...@googlegroups.com


2008/7/7 Eric <xu.ma...@gmail.com>:
其他我不敢说,TAOCP 绝对是启发式的。只有证明是公理式的。

那就以我最近看的n-tuples生成为例。高老大上来就给出一个递归生成格雷码的递归式,搞得我一头雾水。是哪个家伙怎样想到这个递归式的?它是充要的?有没有其它的递归式?本质上是什么?所有可能的格雷码生成式又是什么.. 不管怎样,上来就给出一个充分的做法,这种做法让人摸不着头脑

pongba

unread,
Jul 7, 2008, 9:55:05 AM7/7/08
to pon...@googlegroups.com


2008/7/7 pongba <pon...@gmail.com>:



2008/7/7 Eric <xu.ma...@gmail.com>:
其他我不敢说,TAOCP 绝对是启发式的。只有证明是公理式的。

那就以我最近看的n-tuples生成为例。高老大上来就给出一个递归生成格雷码的递归式,搞得我一头雾水。是哪个家伙怎样想到这个递归式的?它是充要的?有没有其它的递归式?本质上是什么?所有可能的格雷码生成式又是什么.. 不管怎样,上来就给出一个充分的做法,这种做法让人摸不着头脑

TAOCP是《什么是数学》式的书。将知识整理系统化结构化,然后由浅入深的讲。但人类历史上知识的实际积累过程却与此大相径庭。真正的black art是思维,而不是知识本身。

hayate

unread,
Jul 7, 2008, 1:07:10 PM7/7/08
to pon...@googlegroups.com
    我觉得高老头是尽量选择他觉得最有价值的切入点。
    我看具体数学的generation function一章的时候,高老头用一个用基本积木覆盖 n x m 格子的游戏来讲解,中间有一些有意思的细节,比如他不用数学符号,而是直接把积木画出来,用加减乘除连接起来作为式子。后来我猜想他可能是想表达出generation function的性质是一种代数性质,所以强调placeholder,而不是我们容易注意的分析性质,比如级数求和收敛之类。
    而讲二项式公式时,通篇都是不同公式的列举证明,虽然也是有先有后的引入,但是高老头明显不想作任何启发式的讲解,这种tricky的东东只需要记住和使用就行了
    但是作者认为有价值的思路未必是你能接受或者觉得有用的,我有时就不喜欢这种含蓄的意味深长的切入,我觉得还不如赶紧严格证明来得直接。
    常常看到评价同一门课的许多数学教材,说这本观点新颖,那本引入方式特别,这本侧重几何,那本充满了代数云云。我相信不同的作者都在思考怎么更好的表达自己的观点,但是即便这样还是众口难调。我觉得这其实是人与人之间的差异。我觉得一个好的办法是对同一个问题,尽量多找些不同的资料来看,这样往往接受的更快。

2008/7/7 pongba <pon...@gmail.com>:

hayate

unread,
Jul 7, 2008, 1:10:26 PM7/7/08
to pon...@googlegroups.com
什么是数学比起一般数学教材,还是更注重因果和历史的吧

 
2008/7/7 pongba <pon...@gmail.com>:
Message has been deleted

pongba

unread,
Jul 7, 2008, 10:25:35 PM7/7/08
to pon...@googlegroups.com


2008/7/8 EC <NetCl...@gmail.com>:
我们要的不是相对论,而是诞生相对论的那个大脑。<----------------说这句话的人,可能在中国现状中,成绩不是很优秀(猜测),


EC乃知己:D

pongba

unread,
Jul 7, 2008, 10:38:22 PM7/7/08
to pon...@googlegroups.com


2008/7/8 hayate <haya...@gmail.com>:
什么是数学比起一般数学教材,还是更注重因果和历史的吧

恩,我承认。相较而言《什么是数学》已经相当不错了。但毕竟已经是整理过的历史了,实际上历史发展的轨迹根本不是这样规整的,瀑布式的。举一个例子,英文pp277讲的topology里的Brouwer不动点定理,看得我是如坠六里雾中,也不说这定理是从什么需求下面诞生的,也不说定理证明过程的思路。直接就哗啦一下把过程给列出来了,那些精妙的构思怎么就这么出来了呢?囧.. 就好比看A片,谁都不希望MM脱得太快的..

http://www.math.nmsu.edu/~history/
这个地方号称从历史角度还原真实数学,我两年前收藏的链接,但毕竟自己不打算深入数学所以也没有仔细看,有兴趣的同学可以参考。我向来觉得,只有真实的历史是开启未来宝藏的咒语,背完几何原本不能让人成为欧几里德,理解相对论不能让人成为爱因斯坦..

hayate

unread,
Jul 8, 2008, 12:56:11 AM7/8/08
to pon...@googlegroups.com
怎么说呢,我觉得好奇的话可以去了解,但是未必最有效。因为一门学科的发展总是曲折的,充满弯路的。比如我们现在学习微积分,学的不是牛顿莱布尼兹的微积分,一开始就是学得严格化后的微积分。对于那些历史上的事情可以大致了解,但是去仔细研究对于学习未必高效,因为搞不好最开始的东西很粗糙很多都是错的。数学教育工作者在考察这些材料时肯定有所权衡,尽可能高效的教学,而且少走弯路(虽然有时弯路几乎是不可避免的,就像这里我们有太多的为什么,只有弯路可以解释)
总之我觉得这事儿不是作者们不想,而是很难把握分寸,直接按体系列举证明太枯燥,讲太多掌故又容易偏离主题。所以我觉得普通数学教育搭配一点数学史的教育就更好了。
 
ps,我刚才翻了一下古今数学思想,里面也没怎么提到不动点定理的详细来历,只说了Brouwer对拓扑发生了兴趣之后,在研究什么什么问题的时候得到了这个(这些)定理,然后强调这个(这些)定理的意义。我估计更多的细节必须查阅专门的文献了,一般的书都不会讲。不过幸好至少初等情况下,不动点定理还算很直观的。
2008/7/8 pongba <pon...@gmail.com>:

Zhang Zhiqiang

unread,
Jul 8, 2008, 1:09:13 AM7/8/08
to pon...@googlegroups.com
Brouwer不动点就是说你喝汤的时候,无论你怎么搅动,总有一点与原来位置一样 :)
--
zhiqiang

2008/7/8 pongba <pon...@gmail.com>:

pongba

unread,
Jul 8, 2008, 1:12:12 AM7/8/08
to pon...@googlegroups.com


2008/7/8 Zhang Zhiqiang <mat...@gmail.com>:
Brouwer不动点就是说你喝汤的时候,无论你怎么搅动,总有一点与原来位置一样 :)

Zhiqiang兄说的是直观解释。

我其实想知道Brouwer是在面临什么问题的情况下才想到去证明这个定理的,总不会是偶然的发现吧?
还有就是证明里面用的那个巧妙的构造,是怎么想到的。

SpitFire

unread,
Jul 8, 2008, 1:23:34 AM7/8/08
to pon...@googlegroups.com
2008/7/8 pongba <pon...@gmail.com>:

> 我其实想知道Brouwer是在面临什么问题的情况下才想到去证明这个定理的,总不会是偶然的发现吧?
> 还有就是证明里面用的那个巧妙的构造,是怎么想到的。


很多事件就是偶然的,突发的,只可事后预测,但影响深远,比如911

再次推荐《黑天鹅》


--
SpitFire

pongba

unread,
Jul 8, 2008, 1:27:50 AM7/8/08
to pon...@googlegroups.com


2008/7/8 SpitFire <spit...@gmail.com>:

2008/7/8 pongba <pon...@gmail.com>:

> 我其实想知道Brouwer是在面临什么问题的情况下才想到去证明这个定理的,总不会是偶然的发现吧?
> 还有就是证明里面用的那个巧妙的构造,是怎么想到的。


很多事件就是偶然的,突发的,只可事后预测,但影响深远,比如911

"很多事情是偶然的"并不代表"Brouwer定理是偶然的"啊。
 
再次推荐《黑天鹅》

《黑天鹅》是不错的书,看过书评。下了电子书,可作者废话太多,目录也写得一点都不简明,科学理论的东西就好好用科学理论的手法写,搞一堆文学的手法,娱乐性是高了,但对我来说实在是——废话太多。一个简单深刻的道理废话了五百多页,相对论才多少字?

我恨不得他这样写:

案例1:..
案例2:..

结论:..

强烈推荐《合作的进化》,我心目中所有书该有的形式。毫无废话,字字珠玑。

SpitFire

unread,
Jul 8, 2008, 1:45:38 AM7/8/08
to pon...@googlegroups.com
2008/7/8 pongba <pon...@gmail.com>:

>
> 《黑天鹅》是不错的书,看过书评。下了电子书,可作者废话太多,目录也写得一点都不简明,科学理论的东西就好好用科学理论的手法写,搞一堆文学的手法,娱乐性是高了,但对我来说实在是----废话太多。一个简单深刻的道理废话了五百多页,相对论才多少字?


>
> 我恨不得他这样写:
>
> 案例1:..
> 案例2:..
>
> 结论:..
>
> 强烈推荐《合作的进化》,我心目中所有书该有的形式。毫无废话,字字珠玑。


废话是多了点...


--
SpitFire

Googol Lee

unread,
Jul 8, 2008, 2:05:11 AM7/8/08
to pon...@googlegroups.com
是不是说,如果想真正的知其所以然,一定要去了解一下这门学科的历史呢?毕竟任何学科的发展,都和其历史轨迹相关。有可能在某些环节的错误,经过历史冲刷,反而引出了别的发现(记得有这样的例子,想不起来了……)。如果单看结论,很难想到这些相关联系。

2008/7/8 SpitFire <spit...@gmail.com>:



--
新的理论从少数人的主张到一统天下,并不是因为这个理论说服了别人抛弃旧观点,而是因为一代人的逝去。

My blog: http://googollee.blog.163.com

pongba

unread,
Jul 8, 2008, 2:06:34 AM7/8/08
to pon...@googlegroups.com


2008/7/8 Googol Lee <goog...@gmail.com>:

是不是说,如果想真正的知其所以然,一定要去了解一下这门学科的历史呢?毕竟任何学科的发展,都和其历史轨迹相关。有可能在某些环节的错误,经过历史冲刷,反而引出了别的发现(记得有这样的例子,想不起来了……)。如果单看结论,很难想到这些相关联系。

SORRY,没说清楚哈。我说的是广义的历史,比如一个定理证明的来龙去脉,而不仅仅是证明的逻辑本身。

hayate

unread,
Jul 8, 2008, 3:07:14 AM7/8/08
to pon...@googlegroups.com
古今数学思想上说是研究组合不变量的时候发现的,但是这组合不变量是啥我也不知道。
可能问题在于对于当事人来说,定理的发现和证明可能水到渠成,而对于我们来说则需要相当多的背景铺垫,以至于有人觉得这些背景是不必要介绍的。
我知道pongba是希望对于任何定理,都能清晰到把握它诞生发展的脉络,特别是逻辑上。

2008/7/8 pongba <pon...@gmail.com>:

pongba

unread,
Jul 8, 2008, 3:47:00 AM7/8/08
to pon...@googlegroups.com


2008/7/8 hayate <haya...@gmail.com>:

古今数学思想上说是研究组合不变量的时候发现的,但是这组合不变量是啥我也不知道。
可能问题在于对于当事人来说,定理的发现和证明可能水到渠成,而对于我们来说则需要相当多的背景铺垫,以至于有人觉得这些背景是不必要介绍的。
我知道pongba是希望对于任何定理,都能清晰到把握它诞生发展的脉络,特别是逻辑上。

所以我反倒觉得《费马大定理》写得是很好的。尤其是关于威尔斯最后那个早晨(下午?),在百般求索发现弥补不了漏洞的时候,就要放弃间忽然想起,原来之前用过的一个方法可以修改之后来解决现在这个问题。这真是令人感慨万千的事情。令我思考了很久很久。

人脑啊人脑,如此复杂和高级,但却又总是会犯如此低级的错误。

pongba

unread,
Jul 8, 2008, 11:49:46 AM7/8/08
to pon...@googlegroups.com


2008/7/7 pongba <pon...@gmail.com>:



2008/7/7 Eric <xu.ma...@gmail.com>:
其他我不敢说,TAOCP 绝对是启发式的。只有证明是公理式的。

那就以我最近看的n-tuples生成为例。高老大上来就给出一个递归生成格雷码的递归式,搞得我一头雾水。是哪个家伙怎样想到这个递归式的?它是充要的?有没有其它的递归式?本质上是什么?所有可能的格雷码生成式又是什么.. 不管怎样,上来就给出一个充分的做法,这种做法让人摸不着头脑

不过公平的说TAOCP有些地方真的讲得相当漂亮的。譬如令我印象深刻的从竞赛树讲到堆。在其它几本(算法导论、编程珠玑、Algorithms in C、Algorithms)里面对堆的介绍都是上来就定义型的。而从竞赛树来介绍实际上说出了堆这个结构诞生的真正来头。
对了还有上次讨论的那个最有排序。高老大广阅群书,所以能够理清历史脉络。这个优势不是其他作者拥有的,所以很多作者只能流于定义。

谷祖超

unread,
Jul 8, 2008, 12:02:21 PM7/8/08
to pon...@googlegroups.com
在我看来许多问题的求解的确是跟自己的知识面有关系的,某些东西并不需要你懂得已有的算法,重要的是你有广阔的思考方向,逐个方法尝试最终会解决问题,如果方向不够再怎么思考也是没用的。
学算法也类似,并不需要在算法或者数学甚至是计算机方面懂得很多东西,重要的是思考方向,指引你获得更多的知识,这远比单纯的学到一个算法有意义。
有时通过一篇paper来反思作者的思考方向也能获得很多,不要流于paper的表面。

在 08-7-8,pongba<pon...@gmail.com> 写道:

莫华枫

unread,
Jul 8, 2008, 8:04:06 PM7/8/08
to pon...@googlegroups.com


2008/7/8 pongba <pon...@gmail.com>:



2008/7/7 pongba <pon...@gmail.com>:


2008/7/7 Eric <xu.ma...@gmail.com>:
其他我不敢说,TAOCP 绝对是启发式的。只有证明是公理式的。

那就以我最近看的n-tuples生成为例。高老大上来就给出一个递归生成格雷码的递归式,搞得我一头雾水。是哪个家伙怎样想到这个递归式的?它是充要的?有没有其它的递归式?本质上是什么?所有可能的格雷码生成式又是什么.. 不管怎样,上来就给出一个充分的做法,这种做法让人摸不着头脑

不过公平的说TAOCP有些地方真的讲得相当漂亮的。譬如令我印象深刻的从竞赛树讲到堆。在其它几本(算法导论、编程珠玑、Algorithms in C、Algorithms)里面对堆的介绍都是上来就定义型的。而从竞赛树来介绍实际上说出了堆这个结构诞生的真正来头。
对了还有上次讨论的那个最有排序。高老大广阅群书,所以能够理清历史脉络。这个优势不是其他作者拥有的,所以很多作者只能流于定义。
另外一点我觉得也很重要,高大爷本人也是cs很多方面发展的亲历者,有更多的直观理解。


--
刘未鹏(pongba)|C++的罗浮宫
http://blog.csdn.net/pongba
TopLanguage
http://groups.google.com/group/pongba




--
反者道之动,弱者道之用
m...@seaskysh.com
longsh...@gmail.com
http://blog.csdn.net/longshanks/
Reply all
Reply to author
Forward
0 new messages