您有一个已知大小为n的数组或键列表。目前还不知道这个列表中有多少个唯一键,可能只有0,最多包括n。密钥没有特定的顺序,它们实际上不可能,因为这些密钥没有大于或小于,只有相等或不等的概念。现在,在你说哈希映射之前,我认为还有一个条件,就是在这个想法中抛出一个棘手的问题:每个键的值都是私有的。关于密钥,您可以获得的唯一信息是它是否等于另一个密钥。所以基本上:
class key{
private:
T data;
...
public:
...
bool operator==(const key &k){return data==k.data}
bool operator!=(const key &k){return data!=k.data}
};
key array[n];
现在,是否有一种算法可以确定阵列中一半以上的键在线性时间内是否是相同的键?如果没有,那么O(n * log(n))呢?例如,假设数组只有3个唯一键。 60%的数组填充了key.data == foo,30%key.data == bar和10%key.data == derp的键。该算法只需要确定超过50%的密钥属于同一类型(带有data == foo的密钥),并且还返回其中一个密钥。
据我的教授说,它可以在O(n)时间完成,但他说我们只需找到一个可以在O(n * log(n))时间内完成它。
答案 0 :(得分:4)
如果您可以提取并按住任何键进行进一步比较,那么Boyer-Moore Majority Vote Algorithm就是您的朋友。
答案 1 :(得分:0)
如果您不想使用BM算法,您可以使用基于相同想法的以下2算法。
算法a。在每次运行时,保持一组M的M(N的一小部分,例如10)对元素计数,同时为每个元素通过数组:
1.1. If element E is in the set, increase count of the corresponding pair (E,count) -> (E, count+1)
1.2. If not, drop out element with minimal count and insert new pair (E,1)
如果元素具有频率F> 0.5它将在该程序结束时的集合中以概率(非常粗略地,实际上更高)1 - (1-F)^ M,在第二次运行时计算集合S中元素的实际频率。
算法b。取N系列长度为M的随机挑选的阵列元素,通过任意方法选择最频繁的元素并计算其频率和中频串联,频率计算的最大误差为
F(realFrequency)/ sqrt(N)。所以,如果你得到F_e * 1 - 1.0 / sqrt(N))> 0.5然后你找到最常见的元素,如果你得到F_e(1 + 1.0 / sqrt(N))< 0.5这个元素不存在。 F_e是估计的频率。
答案 2 :(得分:-2)
我想到的一个解决方案是..你将从这个数组中选择第一个元素,并遍历列表和你放在一个单独的arraylist中的所有匹配元素,现在你从原始列表中选择第二个元素,如果它们相等,则将它与第一个进行比较,保留此元素并选择下一个元素。这可能是一种可能的解决方案。