问题描述
给定一个长度为n的数组,请找出其中出现次数大于 n/2的元素(假设一定存在)
解决这个问题本身并不困难,大不了建个字典就行。麻烦的是如何在一次遍历、使用O(1)空间解决?这就引出了摩尔投票法。
摩尔投票法
伪代码如下:
Given A of length n;
function findMajorElement(A: array of length n):
int cnt = 0, major = -1;
for i in A:
if cnt == 0:
major = i
cnt = 1
else:
if major == i:
cnt += 1
else:
cnt -= 1
return major
算法背后的逻辑也很简单:想象一个大混战。有很多门派参加,这些门派的弟子功力近似而且讲究武德只单挑不群殴(所以峨眉山的弟子和武当山的弟子碰面了就同归于尽了),但是同门派的不能自相残杀(所以武当山的遇见武当山的就相安无事)。
那么,大混战到最后,自然是人数最多的(超过 n/2)的门派笑到最后啦。