到底该如何学习算法?

俗话说“磨刀不误砍柴工”,虽然我已经开始砍柴,但磨刀还是在继续。除了四处搜罗算法书外,我也看了N多前辈的经验之谈,大到刘未鹏的文章,小到网友们对多本算法书的评论,我都有所吸收,也愈加感到知其所以然的必要性。

很多人学习算法都特别重视代码,不管是伪代码也好还是具体语言代码也好,然而我认为代码不是那么重要的,即使书上只有代码你也不能只拘泥于代码层面,而是应该通过逆向去弄明白这个算法到底是怎么回事,而不能停留在程序运行过程这个表面上。实际上,如果我告诉你一个算法的大体思想,你自己写出实现代码应该是不成问题,而记住思想总比记住代码要容易得多,而同一个思想也可以用于其他问题的解决上,相比之下,代码的价值就逊色很多了。

就拿大家都知道的快速排序来说,快速排序的核心在于其partition函数,《算法导论》既给了伪代码,又画了运行过程,最后给予了证明,看似有些复杂,实际上这个算法还是很容易的。

我最初看了partition函数的伪代码和运行过程后,仅仅停留在感性认识上,所以只是凭着感觉记住了程序的运行过程,并且能够根据这个过程联想到实现代码,但是随着时间的推移,也渐渐淡忘了。后来一天我突然领悟到,partition函数并没有我想象的那么复杂,它的思想很简单:用两个变量i和j,i就像一堵墙,从数组的起始位置(这里设置为0)到i这个位置(包括i)的所有元素都是小于pivot的,我们把这些元素组成的集合起个名字:A,而j从头开始扫描,如果发现有符合小于pivot这个要求的元素,就把它放到集合A中,怎么放呢?先把i这个墙向后移动一位以增加集合A的大小,然后把这个元素和i指向的那个元素交换即可,这样循环下来就保证了集合A中的元素都小于pivot,最后把pivot放到集合A后面就把数组划分成我们想要的那两部分了。

再比如说全排列问题,如果你给一个完全没接触过全排列问题的人一段输出全排列的递归程序的代码,那么十有八九这个人调试半天也不知道这个递归过程到底怎么回事——因为他已经被这个运行过程给搞糊涂了。相反,如果你不告诉他代码而是先给他讲解一下全排列算法具体是怎么回事,那么他也许自己都可以写出代码。

可见,如果只看伪代码和程序的运行过程,不做深入探讨,也只能停留到感性认识的层面:脑中只闪现着一个不断变化的程序运行过程,而不能到形式化层面,更准确地说,不能达到数学的高度上,追根溯源,数学还是起到了举重轻重的作用。在此,引用豆瓣上的一段话来结束本文(来自:http://book.douban.com/review/1319527/):对算法的学习也要从问题本身的数学结构入手,理解解决此种结构问题的算法它的设计思想,掌握分析具有各种结构特征的算法的数学工具,学习怎样发现问题的结构并从中推出问题的下界(lower bound)。这些才是学习算法的根本。

你可能感兴趣的:(Algorithms,关于学习)