所以我在网上发现了这个Google采访算法问题。这真的很有趣,我还没有找到一个好的解决方案。请看一下,给我一个提示/解决方案,如果你能用Java编写代码那将是很好的。)。
“设计一种算法,在给定数组中n个元素的列表的情况下,查找列表中出现次数超过n / 3次的所有元素。 算法应该在线性时间内运行。 (n> = 0) 您应该使用比较并实现线性时间。没有散列/过多空间/并且不使用标准线性时间确定性选择算法“
答案 0 :(得分:8)
我的解决方案受到俄罗斯方块游戏的启发。 解决方案突出显示(称为'Tetrise进程'): 使用三个键值对进行簿记,使用键元素,值元素的计数。在主循环中,我们保留最多3个最新的不同元素。当所有三个键的计数都不为零时,我们减少所有的计数并消除零计数键(如果有的话)。最后,可能存在或可能不存在一些残余元素。这些是俄罗斯方块进程的幸存者。请注意,可以存在不超过3个残余元素。如果什么都没有,我们返回null。否则,我们遍历原始的n个元素,计算这些残余元素的数量,并返回那些计数> 0的元素。 N / 3。
提示证明: 为了证明上述算法的正确性,请注意,元素必须在俄罗斯方块过程中存在或保留在残留物中以满足要求。为了解原因,我们将删除操作的次数表示为m,并将剩余元素的总数r表示。然后我们有 n = 3 * m + r。 从这里得到m&lt; = n / 3,因为r> = 0。 如果一个元素在Tetrise过程中不存在,它可以出现的最大值是m <= n / 3.
时间复杂度O(n),空间复杂度O(1)。
答案 1 :(得分:7)
提示:看看Boyer and Moore's Linear Time Voting Algorithm
更好的提示:首先考虑解决多数问题。也就是说,尝试找到至少n/2
次出现的元素。该算法的基本思想是,如果我们取消元素e
的每次出现,并且所有其他元素与e
不同,则e
将存在,直到结束,如果它是多数元素。
findCandidate(a[], size)
//Initialize index and count of majority element
maj_index = 0;
count = 1;
for i = 1 to n–1 {
if a[maj_index] == a[i]
count++;
else
count--;
if count == 0 {
maj_index = i;
count = 1;
}
}
return a[maj_index]
此算法循环遍历每个元素并保持计数a[maj_index]
。如果下一个元素相同则递增计数,如果下一个元素不相同则递减计数,如果计数达到0,则将maj_index
更改为当前元素并将count设置为1.
接下来,您需要检查此元素确实至少发生n/2
次,但这可以一次完成。