本文正在参加 人工智能创作者扶持计划
本系列分治法重点内容一览:
- 详解当求解子问题与划分+合并子问题时间复杂度相同时,分治法的整体复杂度
- 详解最短点对问题为什么可以做到线性的时间复杂度,包括鸽舍原理等。
【问题描述】
给定平面S上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
蛮力法求解
分别计算每一对点之间的距离,然后找出距离最小的那一对。
应用分治法求解
分治策略
【分治法的求解过程】
- 划分
将集合S分成两个大小基本相等的子集和 - 求解子问题
递归地求解两个子问题 - 合并问题的解
可能出现三种情况
- (1)组成S的最近点对的2个点都在中
- (2)组成S的最近点对的2个点都在中
- (3)组成S的最近点对的2个点分别在和中
比较三种情况下最近点对,取三者之中较小者为原问题的解。
【求解最近点对的分治算法】
预排序:把S 中的点分别按x-坐标值和y-坐标值排序。
为什么要预排序
1. 如果S 中包含的点少于4个(n<4),则采用蛮力法直接求解。
可以直接求解
2. 划分
计算 中各点 x-坐标的中位数 ;
用垂线 把 划分成两个大小相等的子集合 和 , 中的点在 左边, 中的点在 右边。
3. 求解子问题
递归地在 和 中找出最近点对 和 ,设其距离分别为 和
4. 合并解
(1)
(2) 在L两侧查找距离小于 的点对,设其距离为 ;
(3) 如果找到,则 是中最近点对,否则 和 中距离较小者为中最近点对。
的搜索方法及其搜索时间:
搜索范围缩小到以L为中心、宽度为2d的临界区内
对于点,需要考察中的各个点和点之间的距离是否小于,显然, 中这样点的轴坐标一定位于区间之间,即这样的点一定落在一个 的矩形区域内。而且,根据鸽舍原理可知这样的点不会超过6个。
为什么不超过6个?
如图所示,将在实线框起来的矩形区域中找两个子集之间的点的距离,点对于另一个子集 点的距离
为什么将 2d边三等分,因为当相同时,会 与点 距离最近,分治的思想则是将该部分的子问题在纵轴上划分为三块区域,横轴可以划分为两个区域,最终得到6个矩形,作为新的子问题。
为什么它的时间复杂度是线性的?最多和6个点的距离进行比较?
由于鸽舍原理,如果这块矩形区域中超过6个点,比如7个点,那么至少其中一块的矩形区域中至少有两个或多个点
设这两个点为这样的话
当时,距离最大,也即为对角线两端点,此时该距离必然比d要小,这与定义不符,产生了矛盾(两点处于同一子集,其最短距离为或)。
因此得出结论:在该矩形区域内最多只有6个点,也就是说p只需要最多和6个点的距离进行比较即可,这就让该种情况求解子问题的时间复杂度降到了线性。
临界区内所有点构成点集,将其按照坐标排序,对中的每个点依次考察其后的点(最多只要考察紧随其后的7个点),因此,合并步骤可以在线性时间内完成。
//搜索d_3的线性时间实现过程
for(i = 0; i < size(R); i++)
for(j = i + 1; j < size(R); j++)
if(|y(r_i) - y(r_j)| >= d)
break;//继续处理$r_{i+1}$
else
if(distance(r_i,r_j) < d)
d_3 = distance(r_i,r_j);
为什么只需要和紧随其后的7个点进行比较就可以?
根据上面鸽舍原理,每个的矩形区域中最多有一个点,两个子集中最多有12个点,而上下相邻的两块,左边最多有4个点,右边最多有4个点,所以最多共8个点(一个点和紧随其后的7个点),后面的4个点其实是无需进行比较的,因为距离必然超过前7个点。
故而,合并的时间复杂度也可以在线性时间内解决。
【伪代码实现】
double closestPoints(S){
n=|S|
if(n < 4)
采用蛮力法直接求解,返回求得的最近点对值;
m = S中各点x坐标的中位数;
构造S_1和S_2, 其中S_1={x \in S|x \leq m},S_2={x\in S | x > m};
d_1=closestPoints(S_1);
d_2=closestPoints(S_2);
d = min{d_1,d_2);
设距离垂直分割线$L$的距离为$d$的区域为临界区;
构造临界区内所有点组成的集合R(R中的点按照y坐标值有序);
for(i = 0; i < size(R); i++) //size(R)表示集合R中点的个数
for(j = i+1; j < size(R); j++)
if(|y(r_i) - y(r_j)| >= d)
break; //继续处理$r_{i+1}$
else
if(distance(r_i,r_j) < d)
d_3 = distance(r_i,r_j);
return min{d,d3}
【时间复杂度分析】
- 划分阶段需要O(n)时间
- 求解子问题阶段需要2T(n/2)时间
- 合并解阶段需要O(n)时间
- 递归方程
- 用主方法求解T(n)
- 递归方程