2019京东校招笔试题
目录
第一题
题目描述
输入描述
输出描述
分析
- 思路:先整体排序,然后再用滑动窗口对遍历排好序的序列和原始序列,对二者窗口内的集合进行比较,若两集合数据一样,则计数加1;否则窗口继续扩大。
1 | int getMaxTeams(const vector<int>& H) { |
第二题
题目描述
输入描述
输出描述
分析
- 思路:本质是二分图最小顶点覆盖问题(即最大匹配问题,Konig定理)。详见【补充知识点】
1 |
|
补充知识点
二分图
定义:简单来说,图中的点可以分为两组,并且使得所有边都跨越组的边界,这样的图就是一个二分图。
等价定义:不含有奇数条边的环的图。
匹配
匹配(Matching):在图论中,一个匹配是是一个边的集合。其中任意两条边都没有公共顶点。
最大匹配(Maximum Matching):一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
完美匹配(Perfect Matching):如果一个图的某个匹配中,所有顶点都是匹配点,那么它就是一个完美匹配。
匈牙利算法(Hungarian Algorithm)
求解最大匹配问题的一个算法。
交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。
增广路:从一个未匹配点出发,走交替路,如果途经另一个未匹配点(出发的点不算),则这条交替路称为增广路(Augmenting Path)。
增广路的特点:非匹配边比匹配边多一条。因此,只要把增广路中的匹配边和非匹配边的身份交换即可使图中匹配边数目比原来多了1条。由于中间的匹配节点不存在其他相连的匹配边,所以这样做不会破坏匹配的性质。
匈牙利树:一般由BFS构造。从一个未匹配点出发运行BFS(唯一的限制是必须走交替路),直至不能再扩展为止。
匈牙利算法要点:
- 从左边第1个顶点开始,挑选未匹配点进行搜索,寻找增广路。
- 如果经过一个未匹配点,说明寻找成功,更新路径信息,匹配边数+1,停止搜索;
- 如果一直没有增广路,则不再从这个顶点开始搜索。
- 由于找到增广路后需要沿着路径更新匹配,所以我们需要一个结构来记录路径上的点。DFS版本通过函数调用隐式地使用一个栈,而BFS版本使用prev数组。
几个定理:
- 定理1:最大匹配数 = 最小点覆盖数(Konig定理)
- 定理2:最大匹配数 = 最大独立数
- 定理3:最小路径覆盖数 = 顶点数 - 最大匹配数
Konig定理
已知一个二分图的最大匹配数为m。
定理阐释:
标记时交替路性质:
对于一条在交替路上的边(u, v),必定满足:
- u,v均为标号点;
- 若该边为匹配边,则遍历时先走到u,再走到v,即方向为从左至右;
- 若该边为非匹配边,则遍历时先走到v再走到u,即方向从右至左。
为何这是一个点覆盖?
首先可以把边分成两类,一类是在某条交替路上的边,一类不在。
- 对于在交替路上的边,显然可以通过选取左边部分打上标记的点来覆盖掉。
- 而对于不在交替路上且没有被覆盖到的边,它在右边部分的端点一定是没有标记的。
点覆盖的大小为何等于m?
- 由于是交替路,并且起点在右边,所以左边的被标记的点的个数必定和交替路中匹配边的个数相等。
- 非交替路上的且没有覆盖到的边的右端点肯定连到的是未标记的右边的点,而右边每个未被标记的点必定会连且只会连出一条匹配边。
- 两者相加为得到m。
m为何是最小点覆盖?
覆盖m条匹配边最少都要m个点,所以覆盖点显然无法小于这个值。
“ 万物皆有时,比如你我相遇 ”