算法学习的一些看法

以下文字仅代表个人观点和个人经验。
(一)什么是算法
算法是计算机解决问题的方案,伴随着无数新问题的诞生,算法的种类与内容正在不断增加。应用系统的算法设计变得越来越重要。不同的算法可能有不同的效果,也可能会用不同的时间、空间或效率来完成同样的任务。
(二)为什么要学习算法
对计算机专业学生来说,具备基本的算法能力是一项基本要求,在未来的工作之中,只要你还从事技术类工作,算法就是一个绕不过去的门槛。从就业的角度看,企业对大学毕业生的算法要求越来越高,在面试各个阶段都会涉及算法内容,将来不会写代码的“专业人士”肯定会越来越少。未来你的面试官很可能就是一个算法“高手”,也许他会觉得“这么简单的问题”你都不会,你是不是没有 好好学习专业课?(注意,企业面试是一个比较全面的的考查,算法部分只是木桶的一块木板,切不可只关注算法,不关注其他内容
(三)需要学习的算法有那些?
分成两大类:常用的和用不上的。
什么是常用的算法?很简单,就是教材中介绍的算法。
比如说我们这学期数据结构学习的"递归"、“字符串算法”、"矩阵压缩“、查找”、“排序”、“搜索算法”等,这些算法相对简单,未来在工作中的使用率极高。其他课程中的算法:贪心、递推、分治、简单动态规划算法等难度会稍大一点点,但也是在工作中可能用到的算法。(补充一下,一些STL中的数据结构也是很常用的,需要掌握的哦!)
什么是用不上的算法?也很简单,就是你觉得非常难学难记的算法。
以字符串相关算法为例:后缀自动机、字典树、AC 自动机、KMP(你们应该体会到这个算法的恶意哈 )、后缀数组、哈夫曼、Manacher 算法。这些算法中绝大多数应用范围极小,或者可能只存在于竞赛领域,大部分程序员在工作中不会接触这些算法。
再以某动态规划算法题目为例(来自力扣周赛),在3500名参赛选手中只有100余人通过此题,不到3%。此题目对ACM选手来说是一道显而易见的“动态规划”,但对大多数学生来说确实达到了“困难”的难度,没学习过这类算法的同学100%不可能通过。然而在现实工作和生活中哪会有这么“恶心的程序”…。另外,通过的100多人我个人猜测有不少ACMer大佬,因为他们过题的速度比我看题的速度还快…
算法学习的一些看法_第1张图片
总结一下,除了有志于竞赛的同学(大佬)们来说,这些复杂的算法和复杂的数据结构(如字典树、树状数组、线段树等)可以不去学习。但是我们课程中涉及的基础算法是应该掌握的,企业面试的重点是能正确地写出基础算法,面试中的难题能做出来属于锦上添花,做不出来拿个暴力分也很好,对结果来说影响不大。
(四)算法学习的几个阶段
算法的学习次序,定义为四个阶段:
(1)基础算法的熟练掌握(程序设计课程)
所谓的基础算法就是完全不涉及数据结构,只需使用数组、循环、函数即可解决的问题(求极值均值这种简单问题不算基础,那是入门级)。
比如,能快速写出读入不定长数据的代码,用while处理不定长数组,读入0时结束。
i=1;
while(cin>>a[i]&&a[i]!=0)
i++;
n=i-1;//存储在a[1]…到a[n]中。
用双指针法实现数组的逆置;判断质数的正确循环;会用双重循环+条件输出正确的图形(如菱形三角形四边形);会写正确的函数,并且能写出简单的递归函数,如最大公约数函数;简单问题的递推算法;简单的模拟算法(例如用数组模拟约瑟夫环)。
(2)使用基础的数据结构解决经典问题(数据结构课程)
从这个阶段开始难度增大了,开始尝试用数据结构来解决问题。
算法:进制转换、表达式合法性判定、表达式计算、二叉树的各种遍历,图基础算法,二分查找,排序算法等。算法数量、难度、代码量相对于第一学期的程序设计至少多几倍吧。所以我们这个学期需要付出比较多的精力。能熟练写出这些算法,我觉得对于毕业生来说足够了,注意我说的是“熟练”。
(3)更高一级的数据结构与对应算法(需要自学)
专业和非专业的分水岭(大神们别拿特例怼我 )。一些跨专业的同学能很好地掌握(1)(2)的内容,甚至在考研时得到很高的专业分数。但很少见到跨专业的学生能写出更高级别的算法,而在计算机专业还是有非常多同学都能达到这个程度。
这一阶段算法难度进一步增加,特别是很多问题必须使用一些高级数据结构(可参考OJ中的拓展题目)。
算法:简单的动态规划、DFS和BFS搜索、图的遍历和连通性问题、最短路径、最小生成树、拓扑排序,最长(关键)路径,分治算法等。
数据结构:用于查找的三种结构(set、map、priority-queue)、前缀和数组、并查集、树状数组、字典树、线段树等。
达到这个阶段基本上可以做出大多数的企业面试题了,如果是力扣周赛做出前三题没什么问题,第四题看情况。想测试自己能力的话可以看看力扣的“1882. 使用服务器处理任务”,如果你能看出是一个双priority_queue的用法;或者OJ 19008 哈希表,能看出用set或并查集解决;19032 树上上升序列 能看出是拓扑求最长路径;18946 小美的送花线路 能看出是树的最长边。那么你的水平基本上就算达到这个阶段了。
(4)竞赛算法
再提升就属于竞赛范畴了,这不是本篇需要讨论的内容,如有问题去请教ACM大神更好些。
(五)算法到底应该怎么学?
除了极少数“天赋异禀”的人之外,大部分人在学习过程中都会感受到算法的“恶意”。理解算法需要逻辑能力和分析能力,写出正确的代码需要长时间地训练。我觉得很好的一点是,这两件事情都可以通过重复训练得到提升(只要你像我一样时间够多 )。多读题,多做题,多看题解,自己尝试写题解(本人每年也会写几篇 ),这是算法领域被多人证明了的正确学习方法。能做到这些你就会自然而然地具备解(简单 )题和写正确代码的能力。

学习算法需要花费大量的时间,一种好的方式是每天花一两小时进行训练,那么坚持一年左右应该可以达到第三阶段的初级水平。但如果你花费很多时间还是无法进入第三阶段的话,建议就无需再深入下去了,学好其他技术一样可以成为一个好的软件工程师。

学习资源首先是完成我们课程OJ上的基础题目(拓展题目做不出可以先不做),想巩固基础可以去http://ybt.ssoier.cn:8088/index.php去做下基础算法和基础数据结构的题目,这些题目特点是简单直接,不过网站的用户体验并不好。做完这些可以尝试去力扣做下剑指offer的题目,刷一下力扣题库中简单和中等题目。力扣能做中等题目后,在牛客网有很多企业面试真题,可以尝试去看看。

学习过程中尽量独立完成题目,如半小时内没思路或一直写不对代码,再去找题解看,要去记忆那些写的很好的代码。非竞赛选手少用模板,多用手敲。对有价值的题目可以开通博客写题解(费曼学习法),归类和总结。不要去做那些一看就会的题目,要去做看着不太会,但感觉有点思路,有可能做出来题目,或者能想出暴力解法,想不出正解的题目。实在没办法的题目,可百度题解,但绝不要复制代码去提交,哪怕抄也要自己一个一个字符敲进去。

这是一个最好的时代,也是一个最坏的时代。

你可能感兴趣的:(算法,算法,数据结构)