

与同事之间的一段对话,搞得我的小心脏又是扑通扑通的。最起码证明自己坚持在算法这条路上还是有意义的。
平复心情,决定还是写一篇我自己感觉比较好用的几个提升算法技能网站,也当做是做一下自我总结。
学习算法可能会遇到的障碍
有时候我们自认为对一些理论知识已经掌握的足够扎实。比如说链表。相信大多数开发人员对于链表结构不会陌生;对于链表的工作机制了然于心,链表各种操作的时间复杂度也能做到侃侃而谈;甚至于链表的抽象数据类型(ADT)也是信手拈来。但是只要一到实操阶段或者是面试时就各种麻爪。
拆分算法问题
其实仔细总结分析一下,我们在算法面试中,所遇到的问题一般就是那几个固定方向,由浅入深分别是:
1 data structure 数据结构部分
往往是考察应聘者对常用数据结构的理解以及熟练程度。举个例子来说,如果一个软件工程师没有在3分钟以内不能手写出数组 Two Sum 的最优实现,那么一般是认为不合格的。再比如应聘者应该可以快速的描述如何往一个链表中插入一个结点,并阐述其复杂度。
2 algorithm算法部分
这一部分不仅仅是考察对数据结构的熟练程度,还需要考察程序员在解决问题时,是否可以使用效率更高,消耗空间更小的方法。比如在一个有序数组中查找一个元素,并阐述其复杂度。
3 problem solving实际问题的解决
相对前两个阶段就稍微复杂一些。一般情况下会给出一个实际场景,然后列出几条需求或者问题,让应聘者当场给出答案。甚者,有的面试官会让你当场写出代码。这一阶段考察的就是一个程序员的综合素质。比如一个程序员的代码风格,单元测试的水平,遇到棘手问题时是如何去一步一步解决的等等。总之目的无非就是在众多候选人当中选出“能干活,会干活”的那一个。
针对性练习
问题已经剖析完了,那学习算法的方向也就迎刃而解了。总的来说我基本上就是利用以下几个网站分别去学习巩固相应的知识点与技能。
HackerRank, LeetCode, 和 Kattis这几个网站大体上非常相似,但是侧重点又有所不同。
数据结构
针对数据结构方向,我推荐 HackerRank,这个网站有一个专门的数据结构部分(section dedicated to data structures)

1 数组:array rotation, array manipulation
2 链表:reversing a linked list, cycle detection
3 树:node swapping,BST validation
这部分并不会涉及到problem solving的问题,而是各种数据结构的基本操作。这些基本操作非常有助于理解不同数据结构的特性优势。
算法
HackerRank 虽然也有针对算法部分的练习部分–algorithms section。但是对于算法练习,我更倾向于使用 LeetCode,因为 LeetCode 中问题的种类更多,并且往往带有相应的解释部分设置时复杂度的分析。很多人对于庞大的LeetCode不知如何下手,我建议不妨从top 100 liked questions 开始。

- Accounts merge
- Longest continuous increasing subsequence
- Searching in a rotated sorted array
同数据结构部分不同,这一部分的重点并不是去强化巩固数据结构的操作。相反,这一部分的侧重点在于训练解决问题的思维方式。
LeetCode的题目有3中级别的难度:easy,medium, hard。建议初级工程师不要纠结于hard难度级别的题目,重点吃透easy和medium难度即可。
数据结构和算法的实际应用
最终我推荐使用 Kattis 去提升使用数据结构和算法的解决实际问题的技巧。 Kattis Problem Archive 从这里可以找到各种各样的编程实际问题,加以练习,相信对你编程水平会有所提高。
需要注意的是,不要以为这些编程问题会很轻松的解决,有的甚至会让你有挫败感。因为并没有一个官方的解决方案,也没有一个宫大家讨论的论坛(这一点同HankerRank和LeetCode不同)。
其它资源
除了上面提到的3个网站之外,Geeksforgeeks 也是一个学习数据结构和算法非常好的网站。它的优点在于每当讲解一个知识点时,会同时提供多种语言的实现代码片段,比如C++,java,phython等。
总而言之,学习算法是没有捷径可走的。我们必须投入其中,多写多练,多看其他高人的实现代码并加以理解。
