• 分治法--最邻近点对问题


    问题定义:

    输入:空间上n个点的集合Q

    输出:最近点的距离

    定义

    Dis(X,Y)为点X和点Y之间的距离

    Cross(Q1,Q2)为横跨Q1和Q2两个点集的最小距离

    【一维】

    思路:

    1. 划分:将数轴上的点用中位数m分成两个集合

    2. 求解:递归在Q1和Q2中求解子问题

    3. 合并:MIN(Q)= min(MIN(Q1),MIN(Q2),Cross(Q1,Q2))

    时间复杂度分析:

    划分:O(n);求解:2T(n/2);合并:O(1);

    T(n)= 2T(n/2)+O(n)=O(nlogn)

     伪代码:

    //参数A:点的数组(已经按坐标排列)

    //参数low:最左边的点下标

    //参数high:最右边点下标

    Find_MinDis(A,low,high)

            if(high-low == 1)   return Dis(A[low],A[high]);

            else if(high - low > 1)

                      mid = (low+high)/2

                      Left_min = Find_MinDis(A,low,mid)

                      Right_min=Find_MinDis(A,mid+1,high)

                      Cross_min=Dis(A[mid],A[mid+1])

            return Min(Left_min,Right_min,Cross_min);

    【二维】  

    思路:

    划分:  将点按照横坐标的中位数划分成两部分

    记S1和S2中的最小距离d1和d2,设d=min(d1,d2)。

    求解:分别递归的计算出S1和S2的最小距离

    合并:MIN(S)= min(MIN(S1),MIN(S2),Cross(S1,S2))

    问题在于:如何找到横跨S1和S2的两点最小距离

    若使用暴力搜索 ,理论上需要进行n^2/4次计算

    下面使用方法来缩小寻找点的范围:

    1. 容易得知:对S1的任意一个点p来说,满足条件的点一定落在S2中d*2d的范围内

    2. 进一步缩小范围,S2中任意两点距离大于等于d,由抽屉原理得知,任意两点不在同一个小矩形中

    即只需考虑最多6个点

    3. 这样就将时间缩减到6*n/2=3n,即O(n),总的时间复杂度依然是O(nlogn)

  • 相关阅读:
    嵌入式Linux c语言常用数据结构
    Project Euler 9
    串口应用开发的步骤
    创建简单的守护进程的编写规则
    Linux进程间通信信号通信
    [转]linux进程间的通信手段
    守护进程实例
    Linux slab 分配器剖析了解 Linux 内存管理的方式(转)
    嵌入式Linux c语言常用数据结构2
    嵌入式程序员应知道的几个题目(重要)
  • 原文地址:https://www.cnblogs.com/duanshuai/p/13163018.html
Copyright © 2020-2023  润新知