假设我有任意类型的数据集{A,B,C,D},我想将它与另一个数据集进行比较。我想比较{A,B,C,D},{B,C,D,A},{C,D,A,B}和{D,A,B,C},但是不适用于{A,C,B,D}或任何其他类似订购的套装。什么是快速的方法呢?
将它们存储在数组中,旋转并以这种方式进行比较是一个O(n ^ 2)任务,因此不是很好。
我的第一个直觉是将数据存储为{A,B,C,D,A,B,C}之类的集合,然后搜索只有O(n)的子集。这可以更快地完成吗?
答案 0 :(得分:6)
有一种快速算法可以找到字符串的最小旋转 - https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation。因此,您可以存储和比较最小旋转。
答案 1 :(得分:2)
一种选择是使用有向图。设置具有以下过渡的图表:
A -> B
B -> C
C -> D
D -> A
所有其他过渡将使您处于错误状态。因此,如果每个成员都是唯一的(通过使用单词 set 暗示),您将能够确定成员资格,只要您在开始的同一个图节点上结束。
如果某个值在搜索中多次出现,则您需要一组更智能的状态和转换。
如果您预先计算单个搜索,然后将其与许多数据点匹配,则此方法很有用。如果你不得不不断重新生成图表,它就不那么有用了。如果状态表很大,它也可能是缓存效率低的。
答案 2 :(得分:0)
Zoidberg博士,如果您对订单感兴趣,那么您需要将数据存储在一个保留订单并允许轻松轮换的结构中。 在Python中,列表可以。
找到列表中的最小元素,然后旋转要比较的每个列表,直到它们的最小元素位于开头。注意:这不是排序,而是轮换。所有比较列表都被标准化,任何两个之间的直接列表比较会告诉它们在轮换后是否相同。
>>> def rotcomp(lst1, lst2):
while min(lst1) != lst1[0]:
lst1 = lst1[1:] + [lst1[0]]
while min(lst2) != lst2[0]:
lst2 = lst2[1:] + [lst2[0]]
return lst1 == lst2
>>> rotcomp(list('ABCD'), list('CDAB'))
True
>>> rotcomp(list('ABCD'), list('CDBA'))
False
>>>
>>> rotcomp(list('AABC'), list('ABCA'))
False
>>> def rotcomp2(lst1, lst2):
return repr(lst1)[1:-1] in repr(lst2 + lst2)
>>> rotcomp2(list('ABCD'), list('CDAB'))
True
>>> rotcomp2(list('ABCD'), list('CDBA'))
False
>>> rotcomp2(list('AABC'), list('ABCA'))
True
>>>
新部分:与重复?
如果输入可能包含重复,那么(根据问题中提到的可能的双问题),算法是查看一个列表是否是重复两次的另一个列表的子列表。
函数rotcomp2使用该算法和列表内容的repr的文本比较。