Introduction
Finding the majority element in an array is a common coding problem that often appears in technical interviews. The Boyer-Moore Voting Algorithm is one of the most efficient ways to solve this problem in O(N) time and O(1) space.
This guide will cover:
- The problem statement.
- Different approaches and their pros and cons.
- A detailed explanation of the Boyer-Moore Voting Algorithm with examples.
- How to recognize when to use this algorithm.
- Edge cases to consider.
Problem Statement
Given an array nums
of size n
, find the majority element, which appears more thann/2
times.
You must solve this in O(N) time and O(1) space.
Example 1
Input: nums = [3,3,4,2,3,3,3]
Output: 3
Example 2
Input: nums = [2,2,1,1,1,2,2]
Output: 2
Basic Approaches
1. Sorting Approach
- Sort the array.
- The middle element (
nums[n/2]
) will always be the majority element.
Code:
function majorityElement(nums) {
nums.sort((a, b) => a - b);
return nums[Math.floor(nums.length / 2)];
}
Time Complexity: O(N log N)
Space Complexity: O(1)
Downside: Sorting takes extra time, which is unnecessary.
2. Using a Hash Map
- Use a
Map
to count occurrences of each number. - Return the number that appears more than
n/2
times.
Code:
function majorityElement(nums) {
const countMap = new Map();
const n = nums.length;
for (let num of nums) {
countMap.set(num, (countMap.get(num) || 0) + 1);
if (countMap.get(num) > n / 2) return num;
}
}
Time Complexity: O(N)
Space Complexity: O(N)
Downside: Extra space is required to store counts.
Boyer-Moore Voting Algorithm (Optimal Solution)
How It Works
- The majority element appears more than
n/2
times. - If we remove pairs of different numbers, the majority element will always remain.
Algorithm Steps
- Keep a candidate and a count.
- Go through the array:
- If
count == 0
, set the current number as the new candidate. - If the number is the same as the candidate, increase count.
- Otherwise, decrease count.
- If
- The final candidate is the majority element.
Code Implementation
function majorityElement(nums) {
let candidate = null;
let count = 0;
for (let num of nums) {
if (count === 0) {
candidate = num;
}
count += (num === candidate) ? 1 : -1;
}
return candidate;
}
Time Complexity: O(N)
Space Complexity: O(1)
Example Walkthrough
Consider nums = [2, 2, 1, 1, 1, 2, 2]
Index | Number | Candidate | Count | Explanation |
---|---|---|---|---|
0 | 2 | 2 | 1 | First number, set as candidate |
1 | 2 | 2 | 2 | Same as candidate, increase count |
2 | 1 | 2 | 1 | Different number, decrease count |
3 | 1 | 2 | 0 | Different number, decrease count |
4 | 1 | 1 | 1 | Count is 0, set new candidate |
5 | 2 | 1 | 0 | Different number, decrease count |
6 | 2 | 2 | 1 | Count is 0, set new candidate |
Final majority element = 2
Why This Works
- Since the majority element appears more than
n/2
times, it cannot be removed completely. - Non-majority elements cancel each other out.
- By the end, the majority element remains as the last candidate.
When to Use This Algorithm
The Boyer-Moore Voting Algorithm is useful when:
✔ You need to find the most frequently occurring element.
✔ The element appears more than n/2
times.
✔ You need a fast and memory-efficient solution.
Handling Edge Cases
Single Element Array
Input: [1]
Output: 1
All Elements Are the Same
Input: [7,7,7,7]
Output: 7
Already Majority at Start
Input: [3,3,3,3,2,2,1]
Output: 3
Minimum Majority Case
Input: [1,1,2,2,2]
Output: 2
What If We Need to Find Elements Appearing More Than n/3
Times?
The Boyer-Moore algorithm can be extended to find elements appearing more than n/3
times:
- Instead of one candidate, track two.
- Decrease count when neither matches.
- Verify candidates in a second pass.
Code for n/3
Majority Elements
function majorityElementN3(nums) {
let candidate1 = null, count1 = 0;
let candidate2 = null, count2 = 0;
for (let num of nums) {
if (num === candidate1) count1++;
else if (num === candidate2) count2++;
else if (count1 === 0) (candidate1 = num, count1 = 1);
else if (count2 === 0) (candidate2 = num, count2 = 1);
else (count1--, count2--);
}
return [candidate1, candidate2].filter(c => nums.filter(x => x === c).length > nums.length / 3);
}
Final Thoughts
- The Boyer-Moore Voting Algorithm is the most efficient way to find the majority element in O(N) time and O(1) space.
- It works by canceling out non-majority elements using a voting process.
- It can be extended to solve other problems, such as finding elements appearing more than
n/3
times.
This algorithm is widely asked in technical interviews, so understanding it well will help you in coding challenges.