本文写于2015年暑假,当年文笔稚嫩,且内容并不全面,仅供参考。总结内容包括搜索、图论、动态规划、数据结构与数论等。
转载自我的个人网站 https://wzw21.cn/2021/04/13/algorithms/
深度优先搜索(Depth-first Search,DFS),基于递归的搜索方式,它的特点是由一个状态拓展一个状态,然后不停拓展,直到找到目标或者无法继续拓展结束一个状态的递归。可以在数列中进行搜索,也可在坐标系中进行搜索。
广度优先搜索(Breadth-First Search,BFS),基于队列这种数据结构的搜索方式,它的特点是由每一个状态可以扩展出许多状态,然后再以此扩展,直到找到目标状态或者队列中头尾指针相遇,即队列中所有状态都已处理完毕。
DFS:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高
BFS:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。
由于时间和空间的局限性,搜索一般只能解决数据量小的问题。所以我们需要用不同的方法剪枝。剪枝方法包括:
图论是一个应用十分广泛而又极其有趣的数学分支。图即是由若干个不同顶点与连接其中某些顶点的边所组成的图形。
图的存储方式有邻接矩阵、边集数组和邻接表,其中邻接表适用于数据规模比较大的图的存储,也比较好用。
图的遍历有两种遍历方式:深度优先遍历和广度优先遍历。
即求任意两点之间的最短路径。
四种最短路算法:
求图中权值最小的生成树。
两种算法:
适用于有向无环图,使每个点排在它所指向的点的前面。入度为0的入栈,没有就将栈顶元素出栈,将此点删掉。O(v+e)
对于一个强连通分量中的任意一对顶点(u,v),都能够保证分量中存在路径使得u->v,v->u。可缩点成为DAG
两种算法:
当且仅当图的点可被划分为两个内部两两之间没有边的部分。
动态规划(Dynamic Programming,DP)是一种思想与手段。
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
序列型(最长上升子序列)、区间型(石子合并)、棋盘型(过河卒)、划分型(乘积最大)动态规划。
01背包(可用滚动数组)、完全、多重、混合、二维、分组、有依赖。
一些问题状态中所包含的信息过多,如果要用数组来保存状态的话需要四维以上的数组。所以需要通过状态压缩来保存状态。用二进制的一个数来表示一种放法。将1和0分别表示两种状态,二进制数可以表示出所有状态。
数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关
栈,队列,堆,链表,并查集,树(二叉树、多叉树、森林)
是一种查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值。
lowbit(x)=x&-x (-x为x按位取反,末尾+1)。一个节点存这个数二进制下最右边1所对应值到它自己。前缀和Si,顺着i往左上走,修改Ai,从Ci往右上走。
注意是改成一个值还是添加一个值。
线段树是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以求最大值、最小值、区间和等,或者单点修改、区间修改。时间复杂度基本为O(logN)。
注意边的数组范围,一般要开四倍。
N可分成长度根号N的根号N块区间。
(不带修改,询问离线) 先分块,排序(左端点所属块编号,右端点大小);按排序for,转移到下一个时,for出少了的,for掉多了的。
部分可持久化:链形;完全可持久化:树形;
用新建节点取代修改节点信息。(指针、vector)
主席树属于可持久化线段树,求区间第k大,对于序列的每一个前缀建一棵以序列的值为下标的线段树(可离散化),记录该前缀序列里出现的值的次数。
将树剖成不向交的链。向下连size大的,存一个top,树链剖分得到的序列也是dfs序。分成的链(连起来)作为维护的序列。
数论是纯粹数学的分支之一,主要研究整数的性质。
做数论题前,一般先在纸上推出公式或找出规律,再用各种定理或者是方法处理大的数据。
欧几里德即辗转相除,目的是求最大公约数, gcd(a,b)=gcd(b,a%b), 有存在性唯一性,复杂度O(logn);
扩展欧几里德,ax+by=gcd(a,b),求满足的x、y。x1=y2, y1=x2-(a/b)y2;x1与y1的值可由x2、y2推知,拓展欧几里得算法就是不断地的将b放小,直至b等于0,最后反推求回x和y。主要用于解不定方程、解线性同余方程。
注意:x*y=gcd(x,y)*lcm(x,y)
N可以唯一分解成有限个质数的乘积N=p1a1+p2a2+p3a3……+pkak;
唯一性证明:若p|ab,则p|a或p|b。 设n= p1a1+p2a2+p3a3……=q1b1+q2b2……
N为最小的不符合的数,则p1|q1b1+q2b2,即q1q2…中有一个能被p1整除,不妨设为q1,而q1为质数则p1=q1。假设a1>b1,p1a1-b1p2a2…=q2b2q3b3…。同上p1能整除q2,q3…中的数,但p1=q1!=qi 所以不存在a1>b1。同理a1不会小于b1,所以a1=b1。那么n0= p2a2+p3a3……= q2b2……,而n是最小有多种分解的,
所以n0只有一种分解,推出n只有一种分解。
欧拉函数是积性函数,欧拉定理 (a,n)=1则a^φ(n) ≡1(mod n)。
欧拉筛法求欧拉函数,欧拉筛法筛素数即线筛。复杂度 O(n)
线筛:对于当前的一个数i,欧拉筛法把从2,3,5…到小于 i 的最大素数分别和 i 相乘得到的数标记成合数。并且过程中一旦发现 i % (p[j]) == 0,则跳出循环。保证每个合数只被他的最小素因子筛到一次
用到了二分的思想,快速高效的求a^b mod m. O(logn)
将所求的幂不断除以2,改变底数,注意要先乘再模。
矩阵乘法:m × \times ×n与n × \times ×p -> m × \times ×p 。第[i,j] 上的数为矩阵一第i行上的n个数与矩阵二上第j列上的n个数,对应相乘的积之和。
矩阵快速幂,即将矩阵乘进行快速幂,可用于求一些数列。
a^(p-1) ≡ 1 mod m .
a^-1 ≡ a^(φ(m)-1) mod m.
1/a mod m 当m为素数时 =a^(m-2) mod m;
a/b mod m= a mod (mb)/b
(a+b)n=sigma (k=0->n) Cnk*ak*b(n-k)
(a+b)0=1,(a+b)1=a+b,(a+b)2-a2+2ab+b2 与杨辉三角形联系。
两个集合:A∪B =|A∪B| = |A|+|B| - |A∩B |
三个集合:|A∪B∪C| = |A|+|B|+|C| - |A∩B| - |B∩C| - |C∩A| + |A∩B∩C|
P rn = n!/(n-r)! C rn = n!/r!(n-r)!
分治的思想在于将问题划分为子问题来解决。
二分则包括二分查找与二分答案等。若题目要求最大值最小或最小值最大,应考虑二分答案。
找到贪心策略。
各种排序算法。