算法课程总结
算法课程总结
第一章 绪论
算法的特征:
- 有穷性/终止性
- 确定性
- 能行性
- 输入
- 输出
第二章 计算复杂度
计算复杂性函数的阶
详见notability笔记
第三章 分治法的应用
归并排序,快速排序
最大值最小值
棋盘覆盖
中位数
详见Divide and Conquer这篇文章
第四章 动态规划
区间dp
矩阵乘法
最优二分搜索树
线性dp
最长公共子序列
背包问题
详见DP汇总这篇文章
第五章 贪心算法
任务安排问题
哈夫曼编码
最小生成树:Prim, Kruskal
关键其实就是对于优化子结构和贪心选择性的证明
第六章 搜索
爆搜:按照一定的顺序,穷举解空间的每种可能,直到找到问题的答案。
一般的搜索形式:深度优先、广度优先
优化:爬山法、best first、分支界限
爬山法是在深搜基础上加了启发式测度贪心,best first是在宽搜基础上加了评价函数,
分支界限是用于有效求解组合优化问题的,其实也就是最优性剪枝。
旅行商问题、A*算法
这块详见搜索与图论这篇文章。
第七章 摊还分析
摊还分析是为了研究数据结构上操作代价的,一个数据结构可能进行很多不同代价的操作,那么平均地来看,对这个数据结构操作的代价是什么捏,如果采用之前的时间复杂度分析,像处理循环语句之类的处理数据结构操作,没考虑到数据结构本身的特点,得出的结论肯定是有问题的,这时就要考虑具体分析的思路了,也就是摊还分析。
摊还分析的方法主要分为:聚集法,会计法,势能法。
聚集法就是针对每个操作,给出相应的代价,然后对于整体的所有操作,进行求和,然后给出一个上界。说白了就是将整体代价拆为一个一个地去算每个操作的代价。
会计法就是给出一个所有操作的摊还代价表,然后就一劳永逸,得出上界。重点是这个表应该怎样去设计,也就是哪些操作要设置余额,设置多少。这个的话就要具体来看数据结构上的操作了,有些操作是往数据结构里面加东西,比如加数加元素,有些则是让数据结构发生一些变化,关键就是要看一些因果关系,某些操作是另一些操作的前提,利用这点去设计余额。
势能法就是把会计法里面的余额当成整个数据结构的势能了,然后这个势能函数的设计是重点,怎么设计捏,和会计法的思路其实差不多,也是去找因果关系的操作,其实就是为了一些开销很大的操作去积累势能。
课上是主要介绍了几个问题:栈操作,二进制计数器和动态表。
稍微特殊一点的可能是二进制计数器,在考虑会计法和势能法的时候要稍微想一下,其实也蛮显然的,会计法的话就这么想,加数字才能产生进位代价,所以加1操作要设置余额,那么到底该设置多少捏,可以这么想,10000000这种1个1然后全是很多个0的,如果只是设置加1代价为2,会出现最后还少一点,所以考虑0->1的摊还代价是2,这样就欧克了。势能法去分析的话,就是要积攒势能为进位提供余额,进位最猛的时候也就是把所有1变成0,所以如果拿所以1的数量当成势能的话,就可以应对所有操作了。
势能法去分析的时候那个实际代价可以是未知的,拿个字母表示一下就行了,算摊还代价的时候是会消掉的。
然后动态表的话,怎么说捏,记住思路和那个收缩的势能方程即可。
第八章 图论算法
单源最短路径、多源最短路径
网络流算法
匹配问题
这块详见搜索与图论这篇文章。
第九章 字符串匹配
朴素匹配
1 | S[N], p[M]; |
指纹匹配
指纹匹配的原理就是通过计算字符串代表的数值大小,进行匹配。
1 | T[N], P[M] |
Rabin-Karp
模式串p太长的时候,会存在溢出,而且大数的比较常常不是O(1)就能完成的,因此考虑优化,也就是用Hash,mod处理,总的来说就是利用Hash的不同排除大部分不同的情况,然后对于Hash相同的就逐一对比。
参考指纹算法的思路,代码其实也长得差不多,只有一些预处理的不同。
1 | T[N], P[M] |
有限状态自动机
就是对于模式串已经匹配的个数进行枚举,从0~m,然后针对下一个输入的字符的可能,依次计算出状态转移的结果。
1 | //建表过程 |
KMP算法
kmp相对于有限状态自动机的改进是充分结合了字符串本身的特性,其实也是类似一种时间换空间,对于不匹配的过程,不是直接给出表的值,而是利用递归去进行处理,节省空间。
模板
1 | //下标从0开始,若k为已匹配数,则ne[k]表示公共最长前后缀最后一个位置的下一个,也就是新的待判断的位置。 |
朴素逆向
顾名思义,把朴素匹配的循环倒过来就行了
BMH算法
两个点,第一是偏移表的计算,第二是具体去模拟算法的过程。
对比代码看图即可。
后记
属于是寄的比较彻底了😅,虽然基本都是PPT原题吧,但是实际上感觉自己也没咋记住那种,考的雀实烂,我没想到居然考试能这么哈工大hh,其实也是自身原因吧,复习的时候基本就是随性复习,哪里感兴趣就去整哪里,没咋重视ppt的细节实现(>人<;)。
但是通过本学期的算法学习,真的收获了很多,有了算法思维的形成,也是非常棒,对,虽然考试是炸了,但是zxr收获的东西却是美妙的,启发性的(当然考试考的好一点就更好了/(ㄒoㄒ)/~~)。
之前我对于算法的一些理解,要么浅薄,要么就是错的,大一的时候,基本对于算法代码是一窍不通,当时思维好像一直没能转换过来,因为以前都没接触过编程,所以有理解障碍,基本就是停留在数学思维,根本不是计算思维。然后这个状态真的一直就卡了很久,对于算法和编程都是略显抗拒。但是这学期开始,我开始克服这种天然的思维抗拒,去试着理解,虽然上课的时候基本也还是错误的思维吧,直到要考试了,zxr开始考试前一个星期复习(maybe 5 days?),先去刷大量题目,有了机械记忆,然后自己产生很多疑问和很多理解,以及对于问题本质的探究,幸好有mit,极其符合zxr的xp,思路基本都是对口的,然后这才有了正确的认知,虽然可能还是要改进很多,但是基本的原理本质都能窥探到一些了,无奈复习时间真的很短,有些问题还是有疑问的,而且没咋刷题,后续肯定是要解决的。
所以,准确的说,zxr现在才真正的入门了算法,接下来肯定是要持续学习的,原本准备说这个寒假整整6.001来着,现在看来,直接6.006 + 6.046的一部分 + y总其实是比较合适的,其实6.001也是很不错,只是可能不全看了吧,有时间再整整。
So, does it end?
No, just the beginning~