二维平面点集相似问题思考及优化
欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
问题描述
如果两个点集可以通过平移,X轴对称,Y轴对称,中心对称得到相同的点集,则移两个点集相似。
给定多个点集,将所有相似点集归为一组。
上图中所有矩形内的点集是相似的,每一个点集都可以通过平移对称得到其他的点集。
核心思路
- 先将把每一个点集的中心移动到原点
- 每个点集通过对称性复制出另外三份点集
- 对每个点集进行坐标排序
- 通过比对 坐标是否相等判断相似性,点集a与点集b的任一副本相同则为相似。
细节优化
当数据量很大的时候,以上思路会存在性能问题。
有2个优化点
减少复制
在步骤2,3 中,我们要得到三个已经排好序的副本。
但实际上只要对原点集(已经移动到中心)进行2次排序,分别是按照x从小到大(x相同时按照y从小到大)arrX,和按照x从小到大(x相同时按照y从大到小)arrX’
按照以下方法得到4个点集(有序)
- 顺序遍历arrX 可以得到原点集。
- 顺序遍历arrX’ 并令y=-y, 得到关于X轴对称的点集。
- 逆序遍历arrX’ 并令x=-x, 得到关于X轴对称的点集。
- 逆序遍历arrX 并令x=-x, y=-y 可以得到关于原点对称的点集。
减少比较
对于两个点集,如果相似,则两个点集分别产生出来的4个副本必然是一一对称相同的。
所以我们只要比较其中一个相同就可以。
那么我们就取字典序最小的一个来比较。
令arrX 为初始点集,
分别按照上述的2,3,4遍历步骤,并比较与arrX的字典序,如果更小则替换。
得到一个点集后,进行一个内存哈希,哈希会有碰撞概率,进行多重哈希解决冲突问题。
问题升级
有一个超大点集,n个点,给定一个边长l。
每一个点以该点为中心边长为l的正方形内所有点组成一个点集,则有n个这样的点集。
对这n个点集按照相似进行分组。
问题分析
这个的问题在于如何快速生成这n个有序点集(arrX, arrX’)。
之后的处理就和之前分析的一样。
很容易想到利用包围盒查询+排序的方式来实现。
但是,这里相当于排了n次序,是很耗时的。
另一种方式是
1 对超大点集进行排序
2 然后遍历点集每一个点A, 看A属于哪些点B的正方形内,并添加到B的集合中。
以上方法可以保证B有序。
耗时的大头就在第二步,另外B的集合是用数组表示,内存也是很大的挑战。
优化内存
上述方法只要解决内存问题,效率还是可以接受。
我们可以使用分批的形式来解决。
对所有点集进行分块,假设每块的长宽是L=10 * l。
对每一块向外扩展l。 然后对块进行两次排序。
然后遍历点集每一个点A, 看A属于哪些点B(B在当前块中)的正方形内,并添加到B的集合中。
这样B的集合数量不会太多。可以通过调整L大小来控制。
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。