稳扎稳打(一) 知识架构和要点分析
打算写这个系列很久了,看到网上那些大牛一个个都写了很多总结和知识点讲解,逐渐明白自己的不足主要就是在基本功上。很多算法和思路需要重新梳理才能更好的掌握和运用,正好集训还有一个月时间,够自己慢慢的把这些东西梳理完。
在我的认知中,算法分为这几大类:
- 搜索
- 贪心算法
- 数据结构
- 动态规划
- 模拟
- 图论
- 数论
- 几何问题
1.搜索
搜索有很多种方法可供学习和使用,常用的有:
- 宽度优先搜索(BFS)
- 深度优先搜索(DFS)
- 启发式搜索
- 记忆化搜索
这几种搜索方式各有千秋,是很多算法的基础和核心,也就需要将其烂熟于胸。这里先不过多介绍,会单开一篇文章讲这些。
2.贪心算法
贪心算法也有三种公式性质的知识点:
- 区间选点问题
- 区间覆盖问题
- 选择不相交区间问题
可以说大多数的贪心问题都可以转化为这三种问题中的一个进行求解。贪心算法重在策略,这也是贪心和动态规划不好掌握的原因之一,每道题都可能有变化,死记硬背之类的学习方式是万万不可取的。
3.数据结构
说起数据结构,那就真有的说了,作为几乎与算法齐名的一门学科,数据结构在算法中的应用也可称得上是大放异彩。
- 数据结构
- 优先队列,哈希表等基础数据结构
- 并查集
- 区间信息
- 树状数组 (区间求和)
- RMQ问题(区间最小值)
- 线段树 (动态范围最小值)
- 点修改
- 区间修改
- 字符串
- 字典树
- KMP算法
- AC自动机
- 后缀数组
- 最长公共前缀
- 红黑树等(也不是很懂,我还需要补充知识……)
数据结构的学习需要总结和不断地优化,尽量写成自己的模板,这样无论是使用还是修改都不会出现无从下手的情况。
4.动态规划
动态规划(DP)作为重中之重,堪称两个极端的体现:最容易上手,最简单的题目只要四五行代码,但是也最难精进,因为状态转移方程基本上没有相同的,需要不断的思考和总结之前的题目,这是一个循序渐进的过程。动态规划也有一大票的现成理论和题目可以使用:
- 背包问题(重要的很,强烈推荐dd大牛的背包九讲)
- 最长公共子序列
- 最长单调子序列(递增,递减)
- 最优二叉搜索树(不是很懂,<算法导论>上写的)
- 整数划分问题(划分型DP)
- 石子归并问题(区间型DP)
- 旅行家问题
动态规划有很多很多的问题分类,其中很多是相通的,大概可以用这一张图表示(来自 http://wikioi.com/problem/):
动态规划的学习需要花费很多时间,但是一旦入门,就是“柳暗花明又一村”。
5.模拟
模拟在日常的应用中也是很多的,在很多问题中都可以通过模拟来推导出答案,比如基本的大数相加问题,采取模拟来一步步算出结果是最省力的,在时间差距不大的情况下,采取模拟的策略能使程序的复杂度有效地降低。
模拟问题没有什么理论模型,更多的是对现有条件的分析和总结。只要将现有的条件分析的七七八八,问题便迎刃而解。需要注意的是,很多模拟问题都会有大数据的限制,所以使用时间复杂度和空间复杂度尽量小的算法是有效解决模拟问题的关键所在。
6.图论
作为离散数学的重要组成部分,图在算法和实际生活中的应用可谓是桃李满天下。几乎与网状有关的事物,都可以通过图论进行建模和解决。图论中经典的几个模型包括:
- 最小生成树
- 最短路问题
- 网络流
- 费用流
- 二分图匹配
在很多问题中,采用图论的理论来解决问题,会比动态规划更高效,也更容易理解。图论的详细分类可参考下图(来自http://wikioi.com/problem/):
图论的学习,离不开数学理论的支持。如果想好好钻研图论问题,那么,良好的数学基础是必不可少的前提。
7.数论
数论与图论如出一辙,不再赘述(本人的数论功底不是很好,不敢妄加言论)。数论问题大概能分以下几种(来自 http://wikioi.com/problem/):
还是那句话,没有良好的数学功底,图论和数论的学习会比较吃力。希望大家能明白数学的重要性。
8.几何问题
相比数论和图论,几何问题的解决方案要好得多。几何方面有很多的定理可以使用,覆盖的方面也比较广泛。而且分类也比较少:
在我的印象中,几何问题常常和贪心问题组合在一起,例如求解数万个点中的最大多边形面积等等诸如此类的问题。这要求算法的基本功要扎实,能迅速判断出筛选的条件和相应的算法实现。
最后我想说的是,算法的学习很费时间,也很费精力。很多时候,一个问题能困扰我们好几天,百思不得其解。但是,这也是算法的魅力所在。任何能轻易爬上的山峰都不会有美不胜收的景色。
算法的学习更像是一场修行,保持一颗淡定且不断前行的心才是最重要的。急功近利只会让人止步不前,甚至不进反退。