任何一个关键步骤(尤其是本质)的回忆都可能使我们能够自己动手推导出剩余的内
容。譬如你知道堆(heap)是怎样由朴素的决策树演化而来的,它又是为了解决什么问
题的,你即便忘记了具体的细节,也可以自己推导出来。譬如你知道 KMP 算法的本
质在于消除回溯,至于如何消除回溯却并不是那么难以推导的,所以即便忘了也可以
借助于大脑的逻辑演绎能力再现出来。譬如你知道 Tarjan 算法其实只是从后序遍历
经过两个优化调整而来的(其中并査集的使用其实只是优化手段——为了能够迅速判
断祖先节点是谁——而非算法本质——当然,算法设计的主要任务本来就是通过问题
条件中蕴含的知识来“消除冗余计算”和“避免不必要计算”,所以你也可以说并査集的
使用是关乎本质的,只不过,知道了为什么需要引入并査集,就会强烈地感觉到一切
是顺理成章的了),那这个出了名的绕人的算法也就不那么难以理解和记忆了。譬如
你知道排序的本质,就能够对什么是最优排序,为什么它是最优排序有深刻的认识。
四两拨千斤。
� 包含了多得多的知识:记一个算法,就只有一个算法。一个萝卜一个坑。就好比背 99
乘法表只能解决乘法问题一样。而记背后的思想,却有助于解决一类问题。思想所处
的抽象层面往往比到处都是实现细节的算法本身要低,越是低的抽象层次,越是本质,
涵盖范围越是广泛。数学的发展本身就体现了这个过程,抽象代数就是非常好的例子。
算法诞生过程中的思路往往包含了比实际算法更本质得多的知识,实际算法乃至算法
的某个特定语言的实现包含了太多表面的不相干知识,它们会阻碍对本质的理解。
� 重在分析推理,而不是联想:学了一大通算法和数据结构之后的一个副作用就是,看
到一个问题之后,脑袋里立即不管三七二十一冒出一堆可能相干的数据结构和算法来。
联想是强大的思维捷径,在任何时候都会抢占大脑的工作记忆,由不得你控制——比
如我问你“如何寻找区间的最大值”,首先进入你的意识的肯定就是学过的那个算法,
甚至算法的实现细节都一一跳了出来,也许最先跳出来的还是算法实现中某个最容易
弄错的边界细节,或是某个比较 tricky 的实现技巧!然而这些其实根本不反映一个算
法的本质,结果想来想去总是停留在问题的表层。而另一方面,重在思维的传授则可
以让人养成从问题本质入手,逐步分析推理的习惯,而不是直接生搬硬套。当然,完
全不可否认,联想本身也是极其重要的思维方法,甚至可以说是人类思维最重要的特
征。很多时候我们并不知道问题的本质是什么,就需要靠联想、类比来领路探索。只
不过,养成优先从问题的本质入手进行考察的好习惯绝对是有更大的好处的。