改进分治算法的途径2:增加预处理

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个小区域,因为小区域的斜边长d5δ/6,所以一个小区域里面最多只能有一个点,所以右边这个区域最多有6个点有可能满足条件
  • 具体有哪些点在这个范围内呢
  1. 判断点的x坐标,大于x,小于x+δ
  2. 判断点的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变成无序的了)
  • 我们需要判断一个点到底是被划分在左边还是右边
  1. 如果是左边,就把这个点的纵坐标放在左边的递归对应的数组Y[n/2]
  2. 如果是右边,就把这个点的纵坐标放在右边的递归对应的数组Y[n/2]
  3. 此时数组两边的数组Y[n/2]仍然是有序的
  4. 此拆分过程的时间为O(n)

1.3.1 改进算法拆分的实例

输入

P1234
X0.52-21
Y234-1

如图
在这里插入图片描述

  1. 先排序(预处理)
X[n]-2(3)0.5(1)1(4)2(2)
Y[n]-1(4)2(1)3(2)4(3)

括号里的是点的标号

  1. 按照X轴分为两个子数组
XL-2(3)0.5(1)
YL
XR1(4)2(2)
YR

此时这两个Y数组还没填任何数,接下来就填Y数组,也就是第二行表格

  1. 对于y坐标,就要拆分
    一开始预处理的Y[n] 这个数组,先对第一个元素分析 :-1(4),是4号点,而4号点在上一步中按照x坐标应该被分到右边,所以把这个y坐标写到YR里面 ,此时数组变为
XL-2(3)0.5(1)
YL
XR1(4)2(2)
YR-1(4)

同理依次分析元素 2(1)

XL-2(3)0.5(1)
YL2(1)
XR1(4)2(2)
YR-1(4)

分析元素 3(2)

XL-2(3)0.5(1)
YL2(1)
XR1(4)2(2)
YR-1(4)3(2)

分析元素 4(3)

XL-2(3)0.5(1)
YL2(1)4(3)
XR1(4)2(2)
YR-1(4)3(2)

我们可以发现,此时X,Y坐标仍然是排好序的,即省去了每次递归都要重新排序的麻烦

1.3.2 再改进后时间复杂度

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值