为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

知其所以然(续)

2017-12-04 9页 doc 47KB 16阅读

用户头像

is_511210

暂无简介

举报
知其所以然(续)知其所以然(续) 知其所以然(续) By 刘未鹏 – November 14, 2010Posted in: 学习方法, 算法 查了一下,上篇知其所以然(以学习算法为例)是08年7月写的,现在已经是10年11月,过去了两年零4个月,这说明了三件事情:1,一个问题其实你可以一直放在脑子里面,利用暗时间对其软泡硬磨,时间足够久你总会有一点新的感悟,问题其实就像那句老话说的那样,不怕贼偷就怕贼惦记,聚精会神的思考一天,也许比不上惦记一个星期(据说数学家庞加莱就特别会惦记问题)。2,事实上,当你感觉懂了的时候,你至少得反问自...
知其所以然(续)
知其所以然(续) 知其所以然(续) By 刘未鹏 – November 14, 2010Posted in: 学习, 算法 查了一下,上篇知其所以然(以学习算法为例)是08年7月写的,现在已经是10年11月,过去了两年零4个月,这了三件事情:1,一个问其实你可以一直放在脑子里面,利用暗时间对其软泡硬磨,时间足够久你总会有一点新的感悟,问题其实就像那句老话说的那样,不怕贼偷就怕贼惦记,聚精会神的思考一天,也许比不上惦记一个星期(据说数学家庞加莱就特别会惦记问题)。2,事实上,当你感觉懂了的时候,你至少得反问自己一句,真的懂了吗,当你确信自己真的懂了的时候,你至少得讲给别人听,别人听懂了吗,考察你自己是否真懂了的一个很好的依据是,你是否有一种“哦,原来是这样啊,这下再也不可能忘记了”的感觉。3,我其实没有忘记这个博客。如我之前说的,只是学习和思考的副作用,只要还在学习和思考,就必然会有新的记录。 我有一个习惯,看定理必看证明。一个你不明白其证明的定理在我看来比不知道这个定理还要糟糕,因它给你造成一种懂了的错觉。在没有明白背后的证明之前,任何一个定理对你来说都是等价的——等价于背乘法口诀(只不过有的长一点有的短一点)。一个原本美妙的定理,把其证明扔掉就是真正的买椟还珠,暴殄天物。 从现实意义来说,去理解一个定理的证明会带来巨大的好处,首当其冲的好处就是你很难再忘掉它。这一点其实很容易解释——在理解一个定理的证明之前,定理对你而言是一堆没有内在联系的词句,而在理解了证明之后,定理就归约为证明它所需的条件加上逻辑,“逻辑”本来就存在于你的大脑里面,而证明的过程中除了公理和用到的常见定理(往往没几条)之外,宽泛地说,需要你去记的,一般来说也只有一个或两个关键的insights,也就是我们常说的证明中的神来之笔,比如几何证明里面的某条看上去莫名其妙的辅助线,一旦你知道了这条辅助线,那么整个证明就毫无难处,那么该定理的信息量便直接缩减为一条辅助线的信息量;虽然看上去这一步信息并没有缩减多少,但是如果你考虑到类似的辅助线不仅会用在这个特定的定理上,往往会在很多地方用到。很多关键的证明手法是通用的。那么其实你就是把所有以这个辅助线为关键证明手法的定理的集合的信息量归约为了这条辅助线。如果你进而甚至能够理解了作这条辅助线的思想精髓,那就更牛逼了,因为解决问题的思路更具有一般性,理解了寻找正确的辅助线的思路,你就根本不需要去记得某条特定辅助线的作法,你就把所有以作一条或几条辅助线为证明核心的定理的集合的信息量归约为了这个“寻找辅助线的思路”。 这是一个树状的知识结构,越往上层走,需要记忆的节点就越少。所谓触类旁通者,其实便是因为他擅长去理解解法背后的更具一般性的东西。所以我还有一个习惯,就是看到美妙的证明和解法总是会去一遍又一遍的去反复揣摩,试图理解想出这个证明的人到底是怎么想出来的,有没有什么一般性的方法可循,很多 时候,在这样揣摩的过程中,你会理解到更深刻的东西,对问题性质更深刻的认识,对解决问题的思路更深刻的认识,这些认识不仅对于你理解当前这个定理或问题有极大的帮助,同时也有助于你解决以后会遇到的表面不同但本质一样的问题。 与看定理必看证明类似,看一个问题的解法,必然要看解法所诞生的过程,背后是否隐藏着更具一般性的解决问题的思路和原则。否则一个解法就只是一个问题的解法,跟背口诀一样。即便记住了也无法推广,即便当时记住了也容易遗忘。 举个经典的例子:每本算法书都会讲动态规划,每本讲动态规划的书都会讲背包问题,每次讲背包问题都会讲可重复背包和01背包,我们就拿《Algorithms》这本还算不错的算法书对背包问题的讲解来说吧,重复背包问题的递归公式是这样的: K(W) = max { K(W-Wi) + Vi : Wi <= W } 这个公式的理解倒是很简单:为了把问题降阶,我们在最终的最优解里面去掉一个元素,对这个元素的可能性进行讨论,它必然是任何Vi之一(前提是Wi <= W,否则就装不下),而在去掉这个元素之后,剩下的元素肯定构成问题 K(W-Wi) 的最优解,于是递归关系出现了。 此外也可以这样来理解:要拿一组最优元素,那么总得开始一个个拿吧,对第一个拿的元素进行讨论,而问题的最优解等于讨论的各个分支的最优解中的最优者;如果拿掉Vi之后,剩下来要怎么拿才能最优呢,这就是一个 K(W-Wi) 的问题了。 01背包问题就大不一样了——每个物品都只有一件,拿掉之后就不能再拿了。我们不妨看看重复背包问题的解法是不是能用到01背包上呢,还是讨论第一个拿的元素,设被拿掉的是第i个元素,问题就归结为把剩下的物品(注意,可拿的物品少了一件)最优地装入容量为 W-Wi 的包里,所以,问题的参数便变成了两个,一个是背包剩余容量 W-Wi,另一个是剩余可拿的物品集合 S\{i} (表示去掉i之后的子集),显而易见第二个参数是物品集合的各种可能的子集,那么其可能性个数就是 2^n ,这就导致子问题的个数是 2^n, 由于要依次计算每个子问题,那么算法复杂度显然也是 2^n ,是不可接受的。 那么,《Algorithms》上又是怎么来讲解01背包问题的解法的呢,以下是原文: Our earlier subproblems now become completely useless. We must therefore refine our concept of a subproblem to carry additional information about the items being used. We add a second parameter, 0 <= j <= n: K(W, j) = maximum value achievable using a knapsack of capacity w and items 1..j: The answer we seek is K(W, n). 首先作者说了,之前重复背包问题的解法在这里完全废掉了,所以我们必须重新定义子问题,并且子问题的条件必须要包含目前拿剩下的物品。以上这些都还不 错,关键是接下来就让人吐血了。作者接着说道,我们给子问题加上一个新的参数j„ 凭什么啊, 还是让我们回顾一下这样一幅经典的漫画吧: “我们给子问题加上一个参数j”,这就像你在看数学证明时看到无比邪恶的“我们考虑„“一样,一看到这样的句子,你就知道,这个问题的证明远远不像看上去那么简单,之所以你一路看下去理解上全无困难,那完全是因为作者直接把最重要的一个insight告诉你了,举个很简单的例子,证明素数无最大,谁都会第一时间想到去反证:假设存在一个最大的素数P,那么找到比P大的素数就是证明中最关键的一步,怎么找的,一般书上是不会说的,你会看到书上这样说:假设P是最大的素数,那么我们考虑P’ = 小于等于P的所有素数的乘积+1。那么P’一来显然大于P,二来不能被小于它的所有素数整除,那么P’就成了大于P的素数。 如果你经常注意反证法,你会发现一个有趣的现象,反证法里面经常会有这样一句“我们考虑”,而“我们考虑”后面几乎肯定接着一个天外飞仙一般的insight。素数无最大这个古老的证明里面的“我们考虑”尚算是比较有迹可循 的(我们想要构造一个更大的素数,而素数的等价定义就是“不能被小于它的所有素数整除,为了达到这个目的,构造的方法就较明显了)。但是有非常非常多的证明,其中关键的一步就跟嗑药磕出来做梦做出来走路跌跟头跌出来的一样(不信去翻一翻《Proofs from THE Book》),让你完全不知道他怎么想到的。 话说回来,虽然有很多数学证明的关键步骤是很难逆向工程的(因为很多时候想出那个关键步骤的本人其实也是尝试了各种方法,撞了无数堵墙,在寻求证法的尝试空间中作了N次回溯才“妙手偶得”,与其说是妙手偶得,不如说是绞尽脑汁),但并非全无章法可循,否则陶哲轩也不会写出《Solving Mathematical Problems》这样的著作来,而求解问题也就成了真正的Black Art了。 算法的解法则比精妙的数学证明稍加更容易逆向工程一点。只要你有耐心仔细地去琢磨算法的关键步骤和本质,总能从中窥探到一些更general的思想和思路来。 此外,很多经典问题,算法书上的讲法虽然时时令我们失望,但如果去网上一搜,则通常会发现更优秀的解释来。比如背包问题就是如此。 简单地说,如果你对于每个问题都能真正弄清以下这几个问题的答案,那么可以肯定的是,你的理解,记忆,以及学习的效率都会得到质的提高: , 为什么这种解法是对的, , 为什么那种解法是错的, , 为什么这种解法不是最优的, , 证明为什么没有更优的解法。 回到人民群众喜闻乐见的经典例子:背包问题。为什么01背包问题的正确(高效)算法是正确(高效)的。表面的解释是,因为01背包问题的子问题定义是 K(W, j),其两个维度相乘的可能性一共有nW种,也就是说一共要计算nW个子问题,而计算每个子问题的复杂度是O(1)的。 但是如果仅仅满足于这样的解释,可以说是隔靴搔痒,并没有触及到本质。算法本质上可以看做是在一个解空间当中的搜索问题,所以要一个算法的好坏,首先弄清它的解空间的结构,然后分析它是怎么来探索这个解空间的。 弄清解空间的是第一步,例如排序算法,其解空间可以看做是所有可能的下标排列组合,其中有且仅有一个排列是正确的排序排列(简单起见假设元素各不相同)。那么一个算法在探索这个解空间方面的行为就决定了它的效率高低,最简单的,如果一个算法每次只能检查解空间中的一个点,那么这个算法的复杂度就是解空间的大小。对排序算法而言也就是n!。从这个角度来看,我们就会很容易的发现,所有基于比较的排序算法,其复杂度为什么是以O(nlogn)为下界的,因为一次比较操作最多有两个结果,a>b或a
/
本文档为【知其所以然(续)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索