Skip to article
ALGORITHMICSDSA / Arrays
DSAeasy6 min read

Majority Element

Boyer-Moore voting — constant space, and only correct because the problem promises something.


One value appears more than n/2n/2 times. Find it.

majorityElement([]int{2, 2, 1, 1, 1, 2, 2}) // 2

The two answers you already know

Count with a map. O(n)O(n) time, O(n)O(n) space. Correct, obvious, and the sensible default.

Sort and take the middle. A value occupying more than half the positions must cover index n/2n/2 whatever else is there. O(nlogn)O(n \log n), one line, and a nice argument.

Both are fine. The reason this problem is famous is a third answer that uses no extra memory at all.

Boyer-Moore voting

Hold one candidate and one counter. Walk the array. Matching values vote for the candidate, differing values vote against, and when the count hits zero the next value becomes the new candidate.

1 / 7
2 0
2 1
1 2
1 3
1 4
2 5
2 6
candidate
2
count
1

The count had hit zero, so everything before this point cancelled out exactly. Whatever the majority is, it is still the majority of what remains — so 2 becomes the new candidate.

func majorityElement(nums []int) int {
candidate := 0
count := 0
for _, v := range nums {
if count == 0 {
candidate = v
}
if candidate == v {
count++
} else {
count--
}
}
return candidate
}

O(n)O(n) time, O(1)O(1) space, one pass.

The promise it depends on

Generalising to n/3

The same idea extends: at most two values can appear more than n/3n/3 times, so track two candidates and two counters. More than n/kn/k needs k1k-1 of each — the Misra–Gries algorithm, and Boyer-Moore is its k=2k = 2 case.

That generalisation is where it stops being a puzzle and starts being useful. Finding heavy hitters in a stream — the IPs sending the most traffic, the products bought most often — is exactly this, run over data far too large to count exactly.