我有一个部分有序的集合,比如说A = [x1, x2, ...]
,意味着对于集合中的每个xi
和xj
,(确切地说)四种可能性中的一种是真的:{{1} },xi < xj
,xi == xj
或xi > xj
和xi
是无法比拟的。
我想找到最大元素(即没有元素xj
和xi
的元素xj
)。什么是有效的算法(最小化比较次数)?我尝试构建DAG并进行拓扑排序,但只是构建图形需要O(n ^ 2)比较,这太多了。
我在Python中这样做,但如果你不知道,我可以阅读其他语言或伪代码。
答案 0 :(得分:6)
无论你做什么,似乎最坏的情况是O(n ^ 2)。例如,如果没有可比较的元素,那么您需要将每个元素与每个其他元素进行比较,以确定它们都是最大的。
如果你允许O(n ^ 2),因为排序是可传递的,你可以只通过集合进行一次传递,保留到目前为止最大的所有元素的列表;每个新元素都会淘汰任何&lt;它会被添加到最大列表中,如果它不是&lt;任何最大元素。
答案 1 :(得分:3)
在最坏的情况下,你不能比O(n ^ 2)快。实际上要检查所有元素对于没有元素可比较的poset的最大值,您需要比较每对元素。所以在最坏的情况下它绝对是二次方的。
答案 2 :(得分:2)
假设您已经查看了所有(n选择2)比较,除了一个,在x i 和x j 之间,i!= j。在某些情况下,只有两个最大候选者才是这两个,x i 和x j 。
如果你不比较x i 和x j ,你就无法明确地说出它们是否都是最大的,或者是否只有其中一个是。
因此,您必须检查所有可能的(n选择2)(O(n 2 ))比较。
请注意,这假设您的部分有序集使用黑框进行指定,以进行比较。如果部分有序集合以图表的形式给出,您可以随后在子O(n 2 )时间内找到最大元素集合。
答案 3 :(得分:1)
正如其他答案所指出的,最坏的情况复杂性是O(n ^ 2)。
然而,有一些启发式方法可以在实践中提供很多帮助。例如,如果集合A是Z ^ 2(整数对)的子集,那么我们可以预先消除很多点:
这是成本O(n)。很容易看出任何最大点都将出现在xy-maximals中。但是,它可以包含非最大点。例如,考虑集合{(1,0),(0,1),(2,2)}。
根据您的情况,这可能是一个足够好的启发式方法。您可以在较小的集合xy-maximals上使用详尽的算法进行跟进。
更一般地说,这个问题被称为'Pareto Frontier'计算问题。以下是很好的参考资料:
http://www.cs.yorku.ca/~jarek/papers/vldbj06/lessII.pdf
https://en.wikipedia.org/wiki/Pareto_efficiency#Use_in_engineering_and_economics
特别是第一个参考文献中的BEST算法非常有用。