这是我的面试问题,我有点难过。给定k个元素的阵列设计用于确定列表是否具有多数元素的线性时间算法,其中多数元素是在列表中出现多于k / 2次的元素。
答案 0 :(得分:4)
您可以使用O(n)
时间内运行的Boyer's algorithm。它通过阵列两次。
该算法对多数元素使用初始candidate
值,并将计数器count
初始设置为零。
第一遍看起来像这样:
int count = 0;
T candidate = null;
foreach (var element in array) {
if (count == 0) {
candidate = element;
count = 1;
} else {
if (candidate == element) {
count++;
} else {
count--;
}
}
}
如果存在多数元素,candidate
将在循环结束时等于它。但是,如果没有多数元素,候选人可能包含误报。第二遍考虑到了:
count = 0;
foreach (var element in array) {
if (element == candidate) {
count++;
}
}
if (count > array.Length/2) {
Console.WriteLine("Majority element is {0}", candidate);
} else {
Console.WriteLine("No majority element");
}
答案 1 :(得分:2)
您可以将数组的元素散列为整数值,其中元素的值是散列的键,散列的值是数组中每个元素的出现次数的计数。您还可以将最大出现次数存储为最大值;如果最大值> k / 2,该列表具有多数元素,您甚至不需要再次遍历哈希。
答案 2 :(得分:1)
Robert S Boyer和J Strother Moore编写了一种算法,该算法在O(n)时间和O(1)空间中找到大部分,并且可以在线使用,例如存储在磁带上的数据(假设单个倒带)。这个想法是始终保持候选赢家,每次看到候选人时将计数递增1,每次看到其他候选人时将计数递减1,并且每当计数为零时用当前项重置候选人。如果存在多数,则幸存的候选人占多数;这需要单独传递数据,计算候选人的出现次数。 Boyer和Moore(编写字符串匹配算法的人)编写了一个令人愉快的paper,它不仅描述了算法,还描述了他们的FORTRAN 77程序的正式证明。我在my blog的Scheme中有一个实现。
答案 3 :(得分:0)
Create Hashmap, with elements as keys and counters as values
For each item
If the item doesn't have an entry in the hashmap,
Create a counter, starting with a zero value
Increment the counter stored in the hashmap
If the count > k /2
Then this element is the majority element; return true
There is no max if we reach this line; return false