我在python中编写了一个程序,显示输入数据库的最大值集。当一个项目与最大值无法比较时,它将被添加到最大值
目前,我正在整个数据库中执行线性搜索。问题是最坏的情况运行时是O(n ^ 2)。我想知道这个算法可以有更好的实现。
maxima = []
for item in items:
should_insert = 1;
for val in maxima:
comp = self.test(item, val)
if comp == 1:
should_insert = 0
break
elif comp == -1:
maxima.remove(val)
if should_insert == 1:
maxima.append(item)
return maxima
答案 0 :(得分:0)
一般来说,没有办法改善这一点。
但是,部分订单通常有许多线性扩展,可将您的部分订单转换为总订单。 (请参阅http://en.wikipedia.org/wiki/Linear_extension了解我的意思。)假设您可以找到几个在它们之间具有两个元素在原始顺序中具有可比性的属性,当且仅当它们比较时每个人都一样。现在你可以做的是拿你的套装,使用第一个订单做一个堆,直到你发现第一个元素与你的最大值不可比。 (有关该算法的请求,请参阅http://en.wikipedia.org/wiki/Heapsort,在https://docs.python.org/2/library/heapq.html中可以使用该算法。)获取该集合,切换到第二个排序,然后重复。继续,直到您使用了所有订单。
如果您有n
个元素和k
这样的排序,则此算法的最差运行时间为O(k * n * log(n))
。通常情况会好得多 - 如果m
是您在第一步中拉出的组的大小,则运行时间为O(n + k * m * log(n))
。
遗憾的是,您使用此方法的能力取决于您是否可以找到具有此属性的部分排序的几个完整扩展名。但在很多情况下你可以。例如,对于一个订单,您可以在浴室数量上升的情况下打破原始排序,然后在下一个浴室数量下降。等等。
答案 1 :(得分:0)
你的意思并不完全清楚"无与伦比的"值。如果你的意思是相等的值,那么你可能想要一个普通max
函数的简单变体,允许它返回多个相等的值:
def find_maxima_if_incomparable_means_equal(self, items):
it = iter(items)
maxima = [next(it)] # TODO: change the exception type raised here if items is empty
for item in it:
comp = self.test(item, maxima[0])
if comp == 0:
maxima.append(item)
elif comp < 0:
maxima = [item]
return maxima
另一方面,如果你在说某些无法比较的时候(即比较它们没有意义)你的意思是真的,那么情况就更复杂了。你想找到一个&#34; maxima&#34;值的子集,使得最大值集合中的每个项目都大于原始集合中的每个其他项目或与之无法比较。如果您的设置为[1, 2, 3, "a", "b", "c"]
,则您希望最大值为[3, "c"]
,因为整数和字符串无法相互比较(至少在Python 3中没有)。
在一般情况下,没有办法避免O(N^2)
运行时间的潜力。这是因为如果你的任何一件物品都不能与其他物品相比,那么最大值集将最终与整个集合相同,你必须对每一件物品进行测试。其他项目,以确保它们真的无比。
事实上,在最常见的情况下,任何值中都没有要求总排序(例如a < b < c
并不意味着a < c
),您可能需要进行比较每个项目总是与其他项目。这是一个完全正确的功能:
import itertools
def find_maxima_no_total_ordering(self, items):
non_maximal = set()
for a, b in itertools.combinations(items, 2):
comp = self.test(a, b)
if comp > 0:
non_maximal.add(a)
elif comp < 0:
non_maximal.add(b)
return [x for x in items if x not in non_maximal]
请注意,如果比较奇怪且存在周期(例如A < B
,B < C
和C < A
都为真),则此函数返回的最大值可能为空。< / p>
如果您的具体情况更加有限,您可能会有更好的选择。如果您的项目集合是几个完全有序的组的联合(A < B < C
暗示A < C
而A incomparable-to B and B < C
暗示A incomparable-to C
),那么就没有了分离无比组的简单方法,您可以使用与当前代码尝试类似的算法,O(M*N)
其中N
是项目数,M
是数字完全有序的团体。在最糟糕的情况下(O(N^2)
组),这仍然是N
,但如果这些项目最终属于少数几个组,则会更好一些。如果所有项目彼此相当,则O(N)
(并且最大值仅包含单个值)。这是代码的改进版本:
def find_maxima_with_total_orderings(self, items):
maxima = set() # use a set for fast removal
for item in items:
for val in maxima:
comp = self.test(item, val)
if comp == 1:
break
elif comp == -1:
maxima.remove(val)
maxima.add(item)
break
else: # else clause is run if there was no break in the loop
maxima.add(item)
return maxima # you may want to turn this into a list again before returning it
如果项目所属的组可以轻松确定(例如,通过检查项目的类型),您可以做得更好。您可以先将项目细分为其组,然后查找每个完全订购的组的最大值。这是所有情况下代码O(N)
的代码,假设O(1)
运行时方法self.group
返回一些哈希值,以便if { {1}}然后self.group(A) == self.group(B)
:
self.test(A, B) != 0