归并排序
基本思路就是将数组分成二组 A,B,如果这二组组内的数据都是有序的,那么就可以 很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将 A,B 组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
示例:
我们采用2路归并,(start+end)/2处为临界点,将初始无序数组拆分成两个无序序列,然后依次循环拆分,最后再归并为一个新的有序序列;
最长公共子序列
绘制表格来写,填写单元格时使用的公式:
例如 X = { A, B, C, D, D, A, B },Y = { B, D, C, A, B, A }
图如下:
最小生成树(Prim算法和Kruskal算法)
Prim算法
1.基本思想:
- 选择一个起始顶点,然后逐步选择与当前生成树相邻的权值最小的边,并将连接的顶点加入生成树。
- 重复以上步骤,直到生成树包含图中的所有顶点。 2.步骤:
- 从任意顶点开始,初始化一个空的最小生成树。
- 选择一个与当前生成树相邻的边中权值最小的边,将其连接的顶点加入最小生成树。
- 重复上述步骤,直到最小生成树包含了所有顶点。 3.实现细节:
- 使用优先队列(最小堆)来维护当前生成树与其余顶点之间的边。
- 根据贪心策略,每次选择权值最小的边。
例题:
过程;
Kruslal算法
1.基本思想:
- 将图中所有的边按照权值从小到大排序。
- 从小到大遍历排序后的边,如果边的两个端点不在同一个连通分量中,则将这条边加入最小生成树中,并将这两个端点合并为一个连通分量。(也就是新加的边不能与其他边构成环)
2.步骤:
- 对图中所有边按照权值进行排序。
- 初始化一个空的最小生成树。
- 依次考察排序后的边,如果加入某条边不形成环,则将其加入最小生成树中。
3.实现细节:
- 使用并查集(Disjoint Set)来管理连通分量。
- 可以通过贪心的思想逐步加入边,直到所有顶点都在同一连通分量中为止。(也就是加入的边等于所有的顶点-1)
最短路径(Dijkstra算法)
Dijkstra算法步骤如下:
1)初始化:集合S初始化为{0},dist[ ] 的初始值dist[i] = Edge[0][i],path[ ]的初始值path[i] = -1,i = 1,2,...,n-1。
2)从顶点集合 V - S中选出V,满足dist[j] = Min{dist[i] | V (\in) V - S},V就是当前求的一条从 V0 出发的最短路径的终点,令S = S{j}。
3)修改从V0出发到集合 V - S上任一顶点 V 可达的最短路径长度:若 dist[j] + Edge[j][k] < dist[k],则更新 dist[k] = dist[j] + Edge[j][k],并修改path[k] = j(即修改顶点V的最短路径的前驱结点 ) 。
4)重复 2)~ 3)操作共 n-1 次,直到所有的顶点都包含在 S 中。
题目:
过程:
0/1背包问题
有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
公式: (6)i=n时、求出C[n][j],1<=j<=W.即进行i=n行的填表。
由于物品n的重量w=a,v=b,分以下两种情况讨论.
- 如果j<w.即j<a时.C[n][j]=C[n-1][j]。
- 如果j>w,即j>a时,C[n][j]=max{C[n-1][j],C[n-1][j一w]+v}=max{C[n-1][j],C[n-1][j-a]+v}
由于j的取值不同,满足的条件也就有所不同。
求装入背包的具体物品: