时不时会有朋友写信问老赵学习上的一些迷茫,其中都有一些共性。例如说不知道该如何学习,说不知道朝哪个方向前进。也例如大家虽然基本上都知道“算法”的重要性,但是却总觉平时用不到。说它锻炼能力,但“能力”是看不见摸不着的,学着学着就会“麻木”,感觉就“学不进去”了。当然这方面有几个原因,有主观也有客观的,有需要周围环境的改变,也有需要自己精神上“强壮度”的提高。这里呢,我们有时就不提“算法”这个太具体的名词了,而使用“基础”来表示这一类“似乎重要,但不知道重要在哪里”的东西。
还是先从算法,数据结构这类大家从学校里首先都会学到的东西谈起吧。如果说平时用不到算法,那肯定是不可能的。什么是算法?解决问题的方法都是算法,程序中任何对象及其关系都是数据结果。当然您可能会说,这里的说的算法和数据结构是指“有名”的那种,例如大家都耳熟能详的快速排序,图、树等等。当然,说到这个份上,可能就是要分两条路走了。一,您的确只是一直在做普通的CRUD;二,您对于这些知识理解不够,而无法感受到对它们的使用,很多时候我们运用所学的东西是自然而然的——更直接地说出来可能不太中听:“为您掌握的不好,自然觉得没用”。
打个比方,基本上所有的系统都会有“分类系统”,一个大分类下面有多个子分类,子分类下还会有更多子分类。那么现在有了个需求:由于需要垂直地列在一个下拉框中供用户选择,而分类之间的关系使用缩进来表示。在这里分类结构其实就是一颗树,而这个任务其实就是对树的深度优先遍历,于是可能您对书本印象比较深刻的话,就会说用递归,用回溯法。但是不少朋友虽然会解决这问题,解决的方式也不错,可是却没有意识到自己在用什么算法或是数据结构——只是解决了一个问题而已。这其实也比较正常,如果您回忆一下可能就会想起来,学习算法往往都会是依靠“演变”来的,只要具备了一定了逻辑思考能力,算法和数据结构在“一定程度”上也是较为“自然”的东西,并非需要死记硬背。老赵认识个朋友,在做题的过程中把AVL树给彻底忘了——是彻底忘了有这个东西,但是他发现二叉树的退化之后,就自己设法通过旋转来保持平衡。当然这种演变是一种“能力”,我们稍后再详谈。
不过很多时候出现的情况往往都是“不知道”导致“不会做”,至少也是“做不好”。打个比方,在您的程序中会用到大量的容器,您知道System.Collections命名空间下的容器都是用什么数据结构实现,适合什么样的操作吗?如果要求您在图片上打印文字,并且按照固定长度换行,您会使用类似二分法的O(logN)算法,还是直接遍历的O(N)算法呢?再比如把表达式树用作缓存,如果您不了解前缀树,二叉搜索树,以及哈希表的实现方式,可能就只能做出字符串这个低效的选择了。您可能又会想到说,“平时项目真的遇不到”,那么老赵还是重复刚才的话“这个可以遇到”——只是您不知道有其他选择而已。
如果跳出所谓算法和数据结构,其实任何的基础对您工作的作用大都类似。按照老赵之前举过的例子,很多东西都是这样:
- 了解Windows,才能写出更好的.NET应用程序,或者作postmortem调试。
- 了解计算机体系结构,才能在多CPU,多核时代写出真正高效而又正确的应用程序。
- 了解内存分页或线程调度方式,对您应用中设计缓存策略或任务分配有很高的参考价值。
- ……
能够从纷繁复杂的选择之中作出最合理的判断和决策是一种能力,这需要对大量事物进行了解,分析,沉淀,并且能够在脑海中形成映射。如果把人脑看作是一种存储器的话,其中可以就是在一个个单元格中存放着两大类信息:“知识”和“能力”。“知识”可以把问题转化为解决方案,而“能力”则是把知识转化为另一种知识。老赵不知道人脑在得到一个问题的时候是怎么去寻找知识的,这涉及到不同人的索引方式。但是无论是哪种方式,信息越多,查找一次所需要的时间也势必越多。如果没有找到直接能够解决问题的“知识”,则需要一个或多个“能力”把已有知识通过一次或多次转化为另一种,可能是我们原本所没有的知识,而这种能力,我们经常会把他们叫做“推理”,“演变”或者是“融会贯通”能力。
这也就是所谓“能力”最为关键的作用,它们可能也是人类在无法借助外力的情况下唯一获取新知识的途径。
我们假设人脑可以存放的总信息数量确定,在这种情况下,知识太多,能力便少,则获得新知识的成本增加;知识太少,能力虽多,却在解决问题时都需要“推理演变”一番,这也是一种浪费,就好比很少有人会用“公理”去证明一个命题,因为使用“定理”或“推论”效率可以更高。因此,把“知识”和“能力”进行分配是一种艺术,只有达到一种和谐的平衡,一个人才能更好更快地解决问题。
老赵很笨,没有学习的诀窍,唯“埋头苦学”,“勤于思考”把字箴言尔,对我来说无论是“知识”和“能力”都由此而来。有朋友可能会说,我平时不主动学习,等需要的时候再去了解。老赵不同意这个观点,因为这里有个悖论:如果您不自主学习,又如何可以在真正遇到问题的时候知道该使用什么东西呢?做出合适的选择是一个需要积累的过程,而如果不主动学习,很可能最终只会造成重复劳动。就像刚才提到那样,我们需要对大量事物进行了解,分析,沉淀。可能有时候学不进去也要学吧,可能发现美的那一刻,只是因为量变终于引起质变了。
如果您不知道学什么,把大学课本翻出来从头学习,您一定会有所收获的。最近我也在构思一个《老赵书托》系列,希望可以推荐一些好书,对大家有所帮助。
其实引发老赵写下这篇文章的原因是一次(或者说是几次)面试。某培训机构总是打电话来想要“介绍”他们一些学生来公司面试,其语言诚恳让人不忍拒绝。可是一次又一次强调我们需要基础扎实的学生,但是每一次带来的让人很不满意。我在想,他们花了那么长时间读完大学,然后再花大笔大笔的钱去培训机构“进修”,那么多年下来还是如此水平,连我都不由得为他们心痛。当然这样的情况是普遍状况,与是否是某培训机构的学生无关,这是我进行数百次面试中所发现的共同点。例如刚才培训机构的学生,没有一个人能够把一个数组中所有元素反序一下,而一题简单的字符串分割就能考倒9成的面试者。这样的能力让人如何可以接受?理由更加荒唐,有的说“我是学测试的,不是做专业开发的”,“我是做应用的,不熟悉算法”——这种问题算是专业开发吗?算是算法吗?
真心希望现在正在阅读文章的您,就算可以不屑这篇文章,也请你停留片刻,思考一下,您的状况究竟如何呢?