开始复习之前学过的内容,与大家分享下
目标:
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)