所以我有两个数组,每个数组代表一个简单的闭合多边形,按顺序遍历点数组。最后一个元素与第一个元素相同。我正在为任何2个简单的闭合多边形实现一个等于算法。
Array A would be like this [pnt1, pnt2, pnt3, pnt4, pnt5, pnt6, pnt1]
Array B would be like this [pnt2, pnt3, pnt4, pnt5, pnt6, pnt1, pnt2]
Array C would be like this [pnt2, pnt1, pnt6, pnt5, pnt4, pnt3, pnt2]
Array D would be like this [pnt1, pnt2, pnt3, pnt5, pnt6, pnt4, pnt1]
数组A和B是相等的,因为这些点的顺序和点相同。数组A和C是相等的,因为这些点的顺序相同(但相反),出于同样的原因,B和C也是如此。
数组D不等于任何其他数组,因为点遍历无序。
所以我的算法如下:
1)比较数组的长度,必须包含相同的元素数 - 常数时间
2)在B组中找到A [0]为K - 线性搜索,线性时间
3)看A [1] = B [K + 1]等等,直到A [n],线性时间
自然索引会绕过数组的末尾,也许是通过mod运算符。
有没有比这更好的算法?
答案 0 :(得分:2)
要点:
总复杂度:O(n)
注意:步骤3和4不是绝对必要的。从第2步开始,您可以获得最小的位置,并从第3步获取方向。在比较两个不同的数组时,首先从最小值的* location * s开始比较,然后根据方向进行移动。
例如:
[pnt1,pnt2,pnt3,pnt4,pnt5,pnt6,pnt1] - > [pnt1,pnt2,pnt3,pnt4,pnt5,pnt6] - > [pnt1,pnt2,pnt3,pnt4,pnt5,pnt6]
[pnt2,pnt3,pnt4,pnt5,pnt6,pnt1,pnt2] - > [pnt2,pnt3,pnt4,pnt5,pnt6,pnt1] - > [pnt1,pnt2,pnt3,pnt4,pnt5,pnt6]
[pnt2,pnt1,pnt6,pnt5,pnt4,pnt3,pnt2] - > [pnt2,pnt1,pnt6,pnt5,pnt4,pnt3] - > [pnt3,pnt4,pnt5,pnt6,pnt1,pnt2] - > [pnt1,pnt2,pnt3,pnt4,pnt5,pnt6]
[pnt1,pnt2,pnt3,pnt5,pnt6,pnt4,pnt1] - > [pnt1,pnt2,pnt3,pnt5,pnt6,pnt4] - > [pnt1,pnt2,pnt3,pnt5,pnt6,pnt4]
答案 1 :(得分:2)
要进行这样的比较,您可以检查一个数组是否是另一个数组的旋转(最后一个元素除外)。
首先,删除ElKamino指出的重复元素。基本上,你想知道是否可以通过旋转B的元素来获得A.
当A=[x1, x2, ..., xk]
时,B
将以与A相同的顺序具有相同的内容,当且仅当B=[x3, x4, ..., xk, x1, x2]
或类似的内容时。在这种情况下,B可以称为rotation of A
。但是,这还不够,因为您还想检查订单是否相同但是相反。然后,您可以对B
的反向或A
的反向应用相同的过程。
<强>伪代码强>
def isSamePolygon(A, B):
remove the last element of A and last element of B
return isRotation(A, B) or isRotation(A, reverse(B))
def isRotation(A, B): // returns true if A is a rotation of B
// create an array which has two copies of A.
// e.g [a1, a2, ..., ai, a1, a2, ..., ai]
if (size(A) != size(B))
return false
temp_array = concat(A, A)
return true if temp_array contains the elements of B in the exact same order,
false otherwise
<强>分析强>
isRotation
的运行时间和空间复杂度在max(size(A),size(B))的大小上是线性的。这是因为创建temp_array
需要大小为A的线性时间和线性空间。同样,检查A中是否包含B也需要线性时间才能运行。
如果我错了,请纠正我,但使用这种算法,你无法减少渐近的复杂性。但是,您可以优化它以更快地运行。如果size(A)>size(B)
,您可能想要交换A和B.此外;你可以同时检查反向,而不是两个电话。
答案 2 :(得分:2)
如果不允许预处理,这个问题最糟糕的情况是Omega(N),因为在另一个顶点中找到一个多边形的一个顶点可以进行N次比较。
所以没有比你的算法好多了,算法在最佳时间O(N)运行。 [但是,在2和3之间插入一个步骤来确定遍历顺序。]
如果允许预处理,则可以为每个多边形识别(X,Y)字典顺序中的第一个顶点。我们称之为主顶点。通过这样做,您将使算法的第1步无用,因为两个相等的多边形具有相同的主顶点,并且备用线性搜索。
更好的是,您可以通过从主顶点开始计算坐标上的CRC,将签名与多边形相关联。然后,只需通过比较签名,您就可以在时间O(1)中检测到具有高概率的不同多边形。
答案 3 :(得分:1)
我认为“简单”是指没有孔或自交叉的多边形,但是它可能仅在顶点处触及自身。例如,以下内容:
在你的情况下,这种情况可能并不重要,但有些polygon algorithms依赖于这些形状来形成构成复杂多边形的轮廓,因此能够应对它们很方便。
在这种情况下,这两个多边形应该相等:
P = ABCADEAFGAHIAJKA
Q = FGAHIAJKABCADEAF
某些给定的算法可能忽略了这一点,因为P中的第一个(和词典上最小的)顶点A被重复。但是,只要我们知道没有重复 edge ,我们就可以毫不费力地调整算法:
P[0]
中搜索Q
。Q[i]
找到匹配项后,将P[1]
与Q[i-1]
和Q[i+1]
进行比较(并进行适当的包装)。P[0]
中搜索Q
,从Q[i+1]
开始。P
并向前推进Q
。可能会发现不匹配,在这种情况下,多边形不同,您可以立即停止(无需继续搜索P[0]
的其他匹配项),或者您将遍历整个过程,并且它们是相同。顺便说一句,如果你想使用一个算法,需要在轮廓中识别字典上最小的顶点,但是顶点可以重复,你可以通过考虑最小的相邻顶点或顺时针(或计数器)来打破关系 - 时钟,只要你是一致的)邻近的顶点。同样,这取决于不重复的边缘。