情况如下:
我想提取构成完整的坐标组合的子集 大小为N的转角。换句话说;所有笛卡尔坐标都是相邻的。
示例:
findRectangles({
{*(1,1), (3,5), (6,9)},
{(9,4), *(2,2), (5,5)},
{(5,1)},
{*(1,2), (3,6)},
{*(2,1), (3,3)}
})
产生以下结果:
[(1,1),(1,2),(2,1),(2,2)],
...,
...(other solutions)...
同一组中不能有两点。
我首先计算了笛卡尔积,但这很快就变得不可行了(我的用例目前有18个点阵列,每个阵列大致包含10个不同的坐标)。
答案 0 :(得分:5)
您可以使用哈希效果很好:
hash each point (keeping track of which list it is in)
for each pair of points (a,b) and (c,d):
if (a,d) exists in another list, and (c,b) exists in yet another list:
yield rectangle(...)
当我说exists
时,我的意思是做:
hashesToPoints = {}
for p in points:
hashesToPoints.setdefault(hash(p),set()).add(p)
for p1 in points:
for p2 in points:
p3,p4 = mixCoordinates(p1,p2)
if p3 in hashesToPoints[hash(p3)] and {{p3 doesn't share a bin with p1,p2}}:
if p4 in hashesToPoints[hash(p4)] and {{p4 doesn't share a bin with p1,p2,p3}}:
yield Rectangle(p1,p2)
这是O(#bins^2 * items_per_bin^2)
~30000,在您的18个数组和10个items_per_bin的情况下非常快速 - 比外部产品方法好得多......在O(items_per_bin^#bins)
~3万亿的情况下更糟糕。 =)
次要旁注:
您可以通过多次“修剪”来减少计算中的基数和指数。 e.g。
remove each point that is not corectilinear with another point in the X or Y direction
then maybe remove each point that is not corectilinear with 2 other points, in both X and Y direction
您可以根据X坐标进行排序,重复Y坐标,在O(P log(P))
时间内按点数进行排序。您也可以在散列的同时执行此操作。如果一个坏人正在安排你的输入,他可以使这个优化根本不起作用。但根据您的分布情况,您可能会看到显着的加速。
答案 1 :(得分:0)
让XY成为你的数组。构造两个新的X和Y集合,其中X等于XY,所有数组都排序为x坐标,Y等于XY,所有数组都排序为y坐标。
设C为最大数组的大小。然后对所有集合进行排序需要时间O(N * C * log(C))。在步骤1中,找到单个匹配点需要时间O(N * log(C)),因为X中的所有数组都已排序。找到所有这些点是O(C * N),因为总共最多有C * N个点。由于Y被排序,步骤2需要时间O(N * log(C))。
因此,整体渐近运行时在O(C * N ^ 2 * log(C)^ 2)。
对于C == 10和N == 18,您将获得大约10.000次操作。乘以2,因为我因Big-O-notation而放弃了这个因素。
该解决方案的另一个好处是实现起来非常简单。您只需要数组,排序和二进制搜索,其中前两个很可能已经内置到语言中,二进制搜索非常简单。
另请注意,这是最差情况下的运行时,其中所有矩形都从相同的x坐标开始。在一般情况下,你可能会比这更好。