开始复习之前学过的内容,与大家分享下
目标:
INPUT: 平面上的 n 个点
OUTPUT: 欧式距离最近的点对
最原始想法:遍历所有点的集合,具有o(n^2)的时间复杂度
可以使用分治思想进行算法优化.
首先将所有点按照X轴排序(Y轴也可以),之后进行分割为左一半元素,右一半元素,最后左右分别求最近点,最后进行合并,找到左面和右面的点集合里面最小的.
这里的一个trick是找到左右最小距离后,只需要在中间位置使用最小距离约束,如下,左右最小距离是12,只需要考虑中线(-12,12)以内的值就可以,最后递归调用即可
import math import random a=[(500*random.random(), 500*random.random()) for i in range(0,300)] a.sort() par=[] mi=float("inf") def eudis(x,y): global par h=math.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2) if h<mi: par=[] par.append(x) par.append(y) return h def combine(l1,l2,alpha): x=float("inf") mini=l1[-1][0]-alpha maxi=l1[-1][0]+alpha for i in l1: if (mini<i[0]<maxi): for j in l2: if ((mini<j[0]<maxi)and abs(i[1]-j[1])<alpha): x=min(x,eudis(i,j)) return x def divide(a): global mi if (len(a)==2): return eudis(a[0],a[1]) if (len(a)<2): return float("inf") else: i=int(len(a)/2) left = a[0:i] right = a[i:] s1=divide(left) s2=divide(right) s3=combine(left,right,mi) s=min(s1,s2,s3) mi=min(s,mi) return mi jieguo=divide(a)