文章目录
1. 例子:平面点对问题
输入:平面点集P中有n个点,n>1
输出:P中的两个点,其距离最小
1.1 蛮力算法:
- Cn2个点对。(n个点中取两个点计算最小距离)
- O(n2)
1.2 分治算法:P划分为大小相等的PL和PR
- 要么找PL中最近的两个点
- 要么找PR中最近的两个点
- 要么是PL和PR跨边界的两个点
1.|P|<=3,即子集里面的点的个数<=3,就不再分割,直接计算
2.排序,按X轴排一次序,按Y轴排一次序
按X轴排好得到的数组为X[n],按Y轴排好得到的数组为Y[n]
6.先比较左边和右边两个子问题中哪个距离最小,并且把该最小距离记作δ
7.检查距离边界不超过δ的两侧各一个点 的距离
1.2.1 步骤7详解
- 随便检查一个点,假如说这个点是被划分到左侧的点 (当然也可能会被划分到右边,我们不确定,所以后面会说比较12个点,而不是6个点),如图,坐标为(x,y)
那么要想出现的点与这个点的距离小于δ,右边的点只能在这个“日”这个范围内,即长δ,高2δ
- 为什么只能有6个点出现在右边这个范围内?
这是另一张图,整个绿色的就是前面的图上的那个大日
把右边分为6个小区域,因为小区域的斜边长d为5δ/6,所以一个小区域里面最多只能有一个点,所以右边这个区域最多有6个点有可能满足条件 - 具体有哪些点在这个范围内呢
- 判断点的x坐标,大于x,小于x+δ
- 判断点的y坐标,大于y-δ,小于x+δ
因为上面说的那个点也可能被划分到右边,我们想要在它左边找符合条件的点,所以判断的时候,我们直接判断点的x坐标还要大于x-δ,即x坐标要大于x-δ,小于x+δ才符合条件
3. 且肯定不超过12个(左边一个日,右边一个日,而且如果有超过12个了那么δ一定会更小)
4. 怎么确定12个呢,刚好前面已经按照x和按照y排了序,找到两边个6个比较是不是最小
刚刚只是判断第一个点,现在所有的点加一块判断,判断12n次,为O(12n) 量级
1.2.2 时间复杂度
1.3 算法再改进
想要再降低时间复杂度,即要降低O(logn),这是排序造成的
我们可以在递归开始前只对X,Y排一次序
- 这样每次递归沿X轴划分两个平面的时候,只需要X排序的数组X[n]对半砍就行了
- 但Y比较麻烦,因为划分之后的结果仍有可能是乱序的(我们不是按照Y坐标来划分,我们是按照X坐标划分,所以X仍然是有序的,Y变成无序的了)
- 我们需要判断一个点到底是被划分在左边还是右边
- 如果是左边,就把这个点的纵坐标放在左边的递归对应的数组Y[n/2]
- 如果是右边,就把这个点的纵坐标放在右边的递归对应的数组Y[n/2]
- 此时数组两边的数组Y[n/2]仍然是有序的
- 此拆分过程的时间为O(n)
1.3.1 改进算法拆分的实例
输入
P | 1 | 2 | 3 | 4 |
---|---|---|---|---|
X | 0.5 | 2 | -2 | 1 |
Y | 2 | 3 | 4 | -1 |
如图
- 先排序(预处理)
X[n] | -2(3) | 0.5(1) | 1(4) | 2(2) |
---|---|---|---|---|
Y[n] | -1(4) | 2(1) | 3(2) | 4(3) |
括号里的是点的标号
- 按照X轴分为两个子数组
XL | -2(3) | 0.5(1) |
---|---|---|
YL |
XR | 1(4) | 2(2) |
---|---|---|
YR |
此时这两个Y数组还没填任何数,接下来就填Y数组,也就是第二行表格
- 对于y坐标,就要拆分
看一开始预处理的Y[n] 这个数组,先对第一个元素分析 :-1(4),是4号点,而4号点在上一步中按照x坐标应该被分到右边,所以把这个y坐标写到YR里面 ,此时数组变为
XL | -2(3) | 0.5(1) |
---|---|---|
YL |
XR | 1(4) | 2(2) |
---|---|---|
YR | -1(4) |
同理依次分析元素 2(1)
XL | -2(3) | 0.5(1) |
---|---|---|
YL | 2(1) |
XR | 1(4) | 2(2) |
---|---|---|
YR | -1(4) |
分析元素 3(2)
XL | -2(3) | 0.5(1) |
---|---|---|
YL | 2(1) |
XR | 1(4) | 2(2) |
---|---|---|
YR | -1(4) | 3(2) |
分析元素 4(3)
XL | -2(3) | 0.5(1) |
---|---|---|
YL | 2(1) | 4(3) |
XR | 1(4) | 2(2) |
---|---|---|
YR | -1(4) | 3(2) |
我们可以发现,此时X,Y坐标仍然是排好序的,即省去了每次递归都要重新排序的麻烦
1.3.2 再改进后时间复杂度