首先,对于大部分程序员而言,在工作中不是必须的,但是你要找工作,特别是刚毕业参加校招的学生,想进入一些比较大的公司(BAT之流),是必须要学好算法的。
此外,我认为在提高自我技术水平的过程中,比如去阅读一些优秀的代码的时候,也是需要算法功底的,就像去看leveldb、redis源码的时候,起码得知道跳表是个啥吧,看Linux vma的代码得知道红黑树是个啥,看page cache得知道个基数树吧。
再就是有一个很重要的影响:算法学的好的话,不论对你思考问题的方式还是对你编程的思维都会有很大的好处。
另外关于刷题的网站还是首推Leetcode。
如果有一些算法基础的话,推荐Codeforces。
至于资料书籍的话,其实没有太多要求,网上的资料很多,随便谷歌一下就能找到很多详细的资料。
算法导论的话不推荐,不推荐初学者看。这本书是本神书,但是这本书的门槛比较高,需要有一定数学基础和算法基础的人去研究,如果你没有一定的基础或者对算法狂热的学习兴趣,你很难啃下去。
改了一下知识列表的结构,分了下类,可能更加清楚一点。这里面基础是我觉得必须应该掌握的,中等的是有如有余力最好学习的,高级的可以了解,可以了解一下,对于个别感兴趣的可以深入学习一下。
这里面仅仅根据我个人的学习经历去区分难易度,不代表知识本身难易度的精确定位。另外如果大家有什么比较好的补充或者一些问题,可以私信我,我再修改~
1.【数据结构部分】
数据结构我觉得在算法这个概念里的地位是非常重要的,因此还是花一定的精力去学习和练习,看完理论可以刷题,刷完题可以看一些工业级的代码,比如STL源码等,去了解各种数据结构现实应用。
【基础】
链表(单双向链表、循环链表等)、队列(单双向队列)、栈、大/小顶堆、多叉树、排序二叉树(主要熟悉树的前中后序遍历)
【中级】
并查集、树状数组、RMQ、字典树、跳表(非常好用的数据结构,被leveldb、redis等key-value数据库采用)、B/B+树(文件系统中非常常用的数据结构了)、AVL树(平衡二叉树、看懂了为后面的伸展树和红黑树做基础)、线段树(在logn的时间级别内解决区间问题)
【高级】
DLX数独问题、AC自动机(KMP+字典树的结合,在解决大量字符串模板匹配问题上非常好用)、树链剖分(高级数据结构,解决树上的路径更新问题)、伸展树、红黑树(非常出名的数树形据结构、比较复杂,Linux内核中的vma的管理基于这个实现)
2.【图论部分】
图论的话主要是DFS和BFS这两个搜索策略的学习,多熟悉熟悉,不同的实现方法都有什么,比如递归的写法和非递归的写法等等。此外就是最短路的问题,至于一些网络流、图匹配等问题,因为不是打竞赛,仅仅是考虑学习,可以不需要深究。
【基础】
DFS(深度优先遍历)、BFS(广度优先遍历)、拓扑图、最短路问题(Dijkstra)、拓扑排序问题
【中级】
最短路问题(Bellman-Ford、SPFA等)、最小/大割问题、最小生成树、欧拉回路、最近公共祖先(LCA)
【高级】
网络流问题、二分图匹配问题
3.【字符串部分】
字符串的问题其实也在日常应用挺多的,重点了解一下KMP和Hash。
【基础】
字符串哈希(Hash)、回文问题、子串问题
【中级】
KMP算法
【高级】
后缀数组、AC自动机(前面说到过)
4.【数学部分】
数学问题其实没有太多好说的,在学校的同学们还是尽量学好高数、概率论和线性代数吧,这个是一个积累的问题,以后如果进一步的研究和学习,数学肯定是不能太差的,这里就不分类了,只列举一些简单的数学问题。
快速GCD,最大公约数、扩展欧几里得、中国余数定理、求逆元、素数问题
5.【动态规划部分】
动态规划可以说在各种公司的面试中深受广大面试官喜爱,动规(DP)主要还算是一种解决问题的思想,并不是像一个数据结构模型的成型算法,学好的话很难,但是学好动规可以说对你思考问题的方式有很大的提高,这里列一些常见的动规问题的分类。
【基础】
背包问题(0/1背包、完全背包)、最长递增字串问题(LIS)、最长公共子序列(LCS)
【中级】
区间DP、树形DP、数位DP、概率DP、状态压缩DP
【高级】
复杂的DP(经过各种数据结构优化或者各种开脑洞的DP)
6.【几何问题】
-
几何基本运算:求解点与点之间的距离、判断两个点是否重合等基本运算。
-
几何判断问题:判断点是否在多边形内部、判断两线段是否相交、判断线段是否与多边形相交等。
-
几何优化问题:求解最近点对(即找出平面上两点间最近的距离)、求解最小包围圆(即找出包含所有给定点的最小圆)等。
-
几何重建问题:根据给定的几何信息,重构几何结构,如根据点云数据重建三维物体、根据轮廓线重建平面形状等。
7.【其他】
二分查找、贪心问题、各种排序(冒泡排序、归并排序、快速排序、堆排序等)、分治。
最后,也是最重要的:
算法的学习不只是理论的支持,更需要你不断的在理论的基础上去code,去思考