假设我们被给予' n'对象和一个子程序,它接受两个输入并说明它们是否相等(例如,如果它们相等,它可以将输出设为1)。
我需要提出一种算法,该算法调用上述函数O(n log n)次,并确定输入是否超过' n / 2'彼此相同的项目。
答案 0 :(得分:4)
您可以使用Boyer-Moore多数投票算法,该算法最多可进行n-1次比较。
function find_majority(A)
majority = None
count = 0
for a in A:
if count == 0
majority = a
else if a == majority
count += 1
else
count -= 1
return majority
如果在数组中出现的次数超过n / 2次,则返回最常见的元素。
如果你需要知道是否是一个多数项,那么你可以再次通过数组计算从find_majority函数返回的值出现的次数。这增加了另外n个比较。
答案 1 :(得分:3)
这是一个经典的分而治之的解决方案,它给出了O(n log n)
分为两个子集,A1和A2,...,并且显示T(n)是O(n log n)。 如果A具有多数元素v,则v也必须是A1或A2或两者的多数元素。该 等效的反对重述是立即的:(如果v <=每个的一半,则<=总数的一半。)如果两个部分具有相同的多数元素,则它自动成为A的主要元素。如果一个部分中有多数元素,计算两个部分中元素的重复次数(在O(n)时间内),看它是否是多数元素。如果两个部分都占多数,则可能需要对两个候选者中的每一个进行此计数,仍为O(n)。这种分裂可以递归地完成。基本情况是当n = 1时。递归关系是T(n)= 2T(n / 2)+ O(n),因此T(n)是主定理的O(n log n)。
答案 2 :(得分:0)
Paul Hankin的答案是$\mathcal{O}(n)$
解决方案,非常花哨。
如果不使用Boyer-Moore,我们也可以在$\mathcal{O}(nlogn)$
中解决此问题。每次比较之后,我们将“不同”的牌对“丢弃”,并将相等的对“合并”到组中,依此类推,每次我们丢弃相同数量的卡,最后剩下的牌或卡组就是“多数” ”,那么我们可以再次进行比较以检查卡是否为True。
每当我们掉落时,我们至少会掉落一张多数卡和另一张,因此不会影响结果,掉落的过程是“抵消”操作。无论丢弃或合并,都可以帮助我们减少至少一半的卡。因此,递归时间为$logn$
,总时间为$nlogn$
。
答案 3 :(得分:-3)
考虑到序列是有序的,您可以使用binary search
,这需要O(log n)
,因为您必须为每个元素执行此操作,并且您拥有n
元素拿O(n*log n)
。