对于一个问题,你能想到哪些解决问题的算法呢?
注意!!!是算法,不是解法!
如果说“解法”是授之以鱼,那么“算法”便是授之以渔!即是说,解法是针对某一特定问题的具体做法,而算法则是一种看待问题的角度跟解决问题的思想。解法比算法更具体,而算法比解法更具有一般性。
算法体现在数学思维上,以流程图、伪代码为主要的呈现手段。这样就不难理解算法设计中大量采用了数学知识:图论,数论,最优化等等,不胜枚举!
下面给出一份基于巫泽俊老师的《挑战程序设计竞赛》整理而来的基本算法,如有遗漏或不妥,欢迎指正!
1. dfs(深度优先搜索):从某状态开始,不断地转移状态直至无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直到找到最终的解。利用栈进行计算。有时用到剪枝方法。
2. bfs(宽度优先搜索):优先搜索距离初始状态近的状态。利用队列进行计算。
3. 二分法:每次将候选区减小至大约原来的一半。时间复杂度为O(logn)
4. 贪心算法:遵循某种规则寻找最优解。
5. 动态规划(DP):对于同样参数,递归部分只调用一次,第二次之后都直接返回。
6. 二叉搜索树、平衡二叉树:用二叉树的数据结构解决问题。
7. 并查集:用来管理元素分组情况的数据结构。
8. Bellman-Ford算法:d[i] = min{d[j] + (从j到i的边的权值)|e =(j,i)∈E}
9. Dijkstra算法:(1)找到最短距离已经确定的顶点,从它出发更新相邻顶点的最短距离,时间复杂度O(|V|*|E|);(2)从后不需要再关心1中的“最短距离已经确定的顶点”。时间复杂度O(|V|^2)。
10. Floyd-Warshall算法:从0-k分为不经过顶点k(d[k][i][j] = d[k-1][i][j])跟经过顶点k(d[k][i][j] = d[k-1][i][k] +d[k-1][k][j])两种。合起来即为d[k][i][j]= min(d[k-1][i][j], d[k-1][i][k] +d[k-1][k][j])
11. Prim算法、Kruskal算法:求最小生成树问题。前者时间复杂度为O(|E|*log|V|),后者为O(|E|*log|V|)S。
12. 采用数论中知识,如:
a) 辗转相除法:求最大公约数。a = b*p + q,时间复杂度在O(log max(a, b))以内。其扩展形式为扩展欧几里得算法(即求整数x和y使得a*x + b*y = 1)。
b) 费马定理,艾氏筛法,区间筛法。
13. 反复平方法:时间复杂度为O(logn)
14. 蚁群算法:用来在图中寻找最短路径的概率型算法,是一种模拟进化算法。是一种有多样性跟正反馈特点的自组织算法
15. 遗传算法:也是一种自组织算法,与前者区别是给出初始值不断进行评价与选择运算、交叉运算、变异运算来求最优解。
此外还有部分难称算法的技巧也罗列出来:尺取法、反转、弹性碰撞、折半枚举、坐标离散化、巧用栈与队列等数据结构、双端队列、倍增。
这些五一不是基于前面提到的基本算法。
PS:本文虽给出了相当一部分算法的简单解释与证明,但统统绕开了相关数学知识。本人深深理解到想要挨个给出严密的数学证明,非二三十篇blog不能解决。
本文初衷旨在帮助初次接触算法的学生或自学人员理清算法大致框架与思路。但仍需注意算法为一通法思路,解决某一特定问题仍需具体问题具体分析,尽可能的在时间复杂度与空间复杂度做出优化。
如有个人知识不足导致错误、漏洞欢迎给予指正!
因篇幅问题不能全部显示,请点此查看更多更全内容