我有以下序列(代表一棵树):
4 2
1 4
3 4
5 4
2 7
0 7
6 0
现在,我正在尝试对此序列进行排序,这样当左侧(第1列)出现值时,它已经出现在右侧(第2列)。更具体地说,排序算法的结果应该是:
1 4
3 4
5 4
4 2
2 7
6 0
0 7
显然,这在O(n ^ 2)中工作,算法迭代第1列的每个条目,然后在第2列中查找相应的条目。但是因为在我的场景中n可能非常大(> 100000),我正在寻找一种O(n log n)方法来做到这一点。这甚至可能吗?
答案 0 :(得分:2)
<强>假设:强>
我假设这也是一个有效的排序序列:
1 4
4 2
3 4
5 4
2 7
6 0
0 7
即。一旦值出现在右侧,它就会出现在左侧。
如果不是这种情况(即右边的所有出现都必须在左边的任何出现之前),忽略“删除指向该元素的所有边”部分,只有在没有传入的情况下才删除中间元素边缘留下。
<强>算法:强>
构造一个图形,其中每个元素A指向另一个元素B,如果A的右元素等于B的左元素。这可以使用哈希多图来完成:
A
插入哈希映射中A.left -> A
。B
与B.right
下显示的所有元素相关联。执行图表的topological sort,为您提供结果。我应该修改,以便不是删除指向元素的边,而是删除指向该元素的所有边(即如果我们已经在右边找到了包含某个元素的元素,我们不需要为此找到另一个元素元素出现在左边。)
目前这是O(n 2 )运行时间,因为边缘太多 - 如果我们有:
(1,2),(1,2),...,(1,2),(2,3),(2,3),...,(2,3)
有O(n 2 )边缘。
这可以通过以下方式避免,而不是让元素直接指向彼此,而是创建一个中间元素。在上面的例子中,1/2元素将指向该元素,该元素将指向另一半。然后,在进行拓扑排序时,当我们删除该元素的边时,我们会删除该元素以及指向/的所有边。
现在最多有O(n)个边,并且由于拓扑排序可以在相对于元素和边的线性时间内完成,因此整体运行时间为O(n)。
请注意,并非总能获得结果:(1,2), (2,1)
。
<强>插图:强>
对于您的示例(预优化),我们有:
对于我上面的例子,我们有: