Majority Element (LeetCode
Learn how to solve the Majority Element problem using HashMap, Sorting, and the optimal Boyer-Moore Voting Algorithm. Includes intuition, dry run, Java code, complexity analysis, edge cases, interview tips, and production applications.
Introduction
Majority Element is a frequently asked array interview problem that tests whether you can move from a straightforward counting solution to a highly optimized constant-space algorithm.
This problem is commonly associated with companies such as:
- Amazon
- Microsoft
- Meta
- Apple
- Adobe
- Oracle
- Goldman Sachs
- JPMorgan Chase
It evaluates your understanding of:
- Frequency counting
- HashMap usage
- Sorting
- Greedy cancellation
- Boyer-Moore Voting Algorithm
- Time and space optimization
The most important interview insight is that the majority element appears more than half the time, allowing all other values to cancel against it.
Problem Statement
Given an integer array nums, return the element that appears more than:
⌊n / 2⌋
times.
You may assume that the majority element always exists.
Example 1
Input
nums = [3,2,3]
Output
3
Explanation:
graph TD
n_0_0["n"] --> n_1_1["n"]
n_0_0["n"] --> N_2_1_2["2"]
N_3_0_1["3"] --> N_1_1_3["1"]
n_1_1["n"] --> N_3_2_1["3"]
n_1_1["n"] --> appears_2_2["appears"]
N_2_1_2["2"] --> N_2_2_3["2"]
N_2_1_2["2"] --> times_2_4["times"]
N_3_2_1["3"] --> N_2_3_1["2"]
N_3_2_1["3"] --> N_1_3_2["1"]
Therefore, 3 is the majority element.
Example 2
Input
nums = [2,2,1,1,1,2,2]
Output
2
Explanation:
graph TD
n_0_0["n"] --> n_1_1["n"]
n_0_0["n"] --> N_2_1_2["2"]
N_7_0_1["7"] --> N_3_1_3["3"]
n_1_1["n"] --> N_2_2_1["2"]
n_1_1["n"] --> appears_2_2["appears"]
N_2_1_2["2"] --> N_4_2_3["4"]
N_2_1_2["2"] --> times_2_4["times"]
N_2_2_1["2"] --> N_4_3_1["4"]
N_2_2_1["2"] --> N_3_3_2["3"]
What Does Majority Mean?
A majority element appears more than half of the total array length.
For an array of size n:
Frequency > n / 2
Examples:
| Array Size | Majority Frequency |
|---|---|
| 1 | At least 1 |
| 3 | At least 2 |
| 5 | At least 3 |
| 6 | At least 4 |
| 10 | At least 6 |
There can be only one majority element.
Two different values cannot both appear more than n / 2 times.
Approach 1 — Brute Force
Idea
For every element:
- Count how many times it appears.
- If the count is greater than
n / 2, return it.
Brute Force Flow
graph TD
Current_Element["Current Element"] --> Scan_Entire_Array["Scan Entire Array"]
Scan_Entire_Array["Scan Entire Array"] --> Count_Occurrences["Count Occurrences"]
Count_Occurrences["Count Occurrences"] --> Majority["Majority?"]
Majority["Majority?"] --> Return["Return"]
Java Code — Brute Force
public class MajorityElementBruteForce {
public int majorityElement(int[] nums) {
int majorityCount = nums.length / 2;
for (int candidate : nums) {
int count = 0;
for (int value : nums) {
if (value == candidate) {
count++;
}
}
if (count > majorityCount) {
return candidate;
}
}
throw new IllegalArgumentException(
"Majority element does not exist");
}
}
Complexity
| Complexity | Value |
|---|---|
| Time | O(n²) |
| Space | O(1) |
This approach is easy to understand but inefficient for large arrays.
Approach 2 — HashMap Frequency Counting
Core Idea
Store the frequency of every number in a HashMap.
For each element:
- Increase its count.
- Check whether the count is greater than
n / 2. - Return immediately when the majority threshold is reached.
HashMap Flow
graph TD
Read_Number["Read Number"] --> Update_Frequency["Update Frequency"]
Update_Frequency["Update Frequency"] --> Frequency_n_2["Frequency n / 2?"]
Frequency_n_2["Frequency n / 2?"] --> Return_Number["Return Number"]
Java Code — HashMap
import java.util.HashMap;
import java.util.Map;
public class MajorityElementUsingHashMap {
public int majorityElement(int[] nums) {
Map<Integer, Integer> frequencies =
new HashMap<>();
int majorityCount = nums.length / 2;
for (int number : nums) {
int count = frequencies.merge(
number,
1,
Integer::sum);
if (count > majorityCount) {
return number;
}
}
throw new IllegalArgumentException(
"Majority element does not exist");
}
}
Alternative HashMap Implementation
import java.util.HashMap;
import java.util.Map;
public class MajorityElementUsingGetOrDefault {
public int majorityElement(int[] nums) {
Map<Integer, Integer> frequencies =
new HashMap<>();
for (int number : nums) {
frequencies.put(
number,
frequencies.getOrDefault(number, 0) + 1);
}
for (Map.Entry<Integer, Integer> entry
: frequencies.entrySet()) {
if (entry.getValue() > nums.length / 2) {
return entry.getKey();
}
}
throw new IllegalArgumentException(
"Majority element does not exist");
}
}
Complexity
| Complexity | Value |
|---|---|
| Time | O(n) |
| Space | O(n) |
This is efficient but requires additional memory.
Approach 3 — Sorting
Core Idea
If the array is sorted, the majority element must occupy the middle position.
Why?
Because it appears more than half the time.
After sorting:
Majority Element
↓
Must Cross Middle Index
Therefore:
nums[nums.length / 2]
is guaranteed to be the majority element.
Example
Input:
[2,2,1,1,1,2,2]
After sorting:
[1,1,1,2,2,2,2]
Middle index:
7 / 2 = 3
Value:
nums[3] = 2
Java Code — Sorting
import java.util.Arrays;
public class MajorityElementUsingSorting {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
Complexity
| Complexity | Value |
|---|---|
| Time | O(n log n) |
| Space | O(log n) or implementation-dependent |
This solution is concise but modifies the input array.
Approach 4 — Boyer-Moore Voting Algorithm
Core Idea
The Boyer-Moore Voting Algorithm finds the majority element in:
O(n) time
O(1) space
It works using a cancellation principle.
Maintain:
candidatecount
Rules:
- If
count == 0, choose the current number as the new candidate. - If the current number equals the candidate, increment the count.
- Otherwise, decrement the count.
Cancellation Intuition
Suppose the majority element is 2.
Input:
[2,2,1,1,1,2,2]
Pair each non-majority value with one majority value.
2 cancels 1
2 cancels 1
2 cancels 1
Since 2 appears more than half the time, at least one 2 must remain after all cancellations.
The final surviving candidate is the majority element.
Algorithm
graph TD
candidate_undefined["candidate = undefined"] --> count_0["count = 0"]
count_0["count = 0"] --> Read_Number["Read Number"]
Read_Number["Read Number"] --> count_01["count == 0?"]
count_01["count == 0?"] --> Set_New_Candidate["Set New Candidate"]
Set_New_Candidate["Set New Candidate"] --> Same_as_Candidate["Same as Candidate?"]
Dry Run
Input:
[2,2,1,1,1,2,2]
Step 1
Current value:
2
Since:
count = 0
Set:
candidate = 2
Then:
count = 1
Step 2
Current value:
2
Matches candidate.
count = 2
Step 3
Current value:
1
Does not match candidate.
count = 1
Step 4
Current value:
1
Does not match candidate.
count = 0
Step 5
Current value:
1
Since count is zero:
candidate = 1
Then:
count = 1
Step 6
Current value:
2
Does not match candidate.
count = 0
Step 7
Current value:
2
Since count is zero:
candidate = 2
Then:
count = 1
Final candidate:
2
Dry Run Table
| Current Value | Candidate Before | Count Before | Action | Candidate After | Count After |
|---|---|---|---|---|---|
| 2 | — | 0 | Select candidate | 2 | 1 |
| 2 | 2 | 1 | Increment | 2 | 2 |
| 1 | 2 | 2 | Decrement | 2 | 1 |
| 1 | 2 | 1 | Decrement | 2 | 0 |
| 1 | 2 | 0 | Select candidate | 1 | 1 |
| 2 | 1 | 1 | Decrement | 1 | 0 |
| 2 | 1 | 0 | Select candidate | 2 | 1 |
Java Code — Optimal Solution
public class MajorityElement {
public int majorityElement(int[] nums) {
int candidate = 0;
int count = 0;
for (int number : nums) {
if (count == 0) {
candidate = number;
}
if (number == candidate) {
count++;
} else {
count--;
}
}
return candidate;
}
}
Cleaner Java Implementation
public class Solution {
public int majorityElement(int[] nums) {
int candidate = nums[0];
int count = 0;
for (int number : nums) {
if (count == 0) {
candidate = number;
}
count += number == candidate ? 1 : -1;
}
return candidate;
}
}
Complexity Analysis
| Complexity | Value |
|---|---|
| Time | O(n) |
| Space | O(1) |
This is the optimal solution.
Why Boyer-Moore Works
Assume the majority element is M.
Because M appears more than n / 2 times:
Frequency(M) > Frequency(all other elements combined)
Every time a different value appears, it cancels one occurrence of the current candidate.
Even after all possible cancellations, the majority element still has unmatched occurrences.
Therefore, the final candidate must be the majority element.
Formal Intuition
Let:
m = count of majority element
o = count of all other elements
Since:
m > o
After pairing each non-majority element with one majority element:
m - o > 0
At least one majority element remains.
Is Verification Required?
For LeetCode #169, verification is not required because the problem guarantees that the majority element exists.
However, in a general production scenario, the candidate should be verified.
Boyer-Moore with Verification
public class MajorityElementWithValidation {
public int majorityElement(int[] nums) {
int candidate = 0;
int count = 0;
for (int number : nums) {
if (count == 0) {
candidate = number;
}
count += number == candidate ? 1 : -1;
}
int frequency = 0;
for (int number : nums) {
if (number == candidate) {
frequency++;
}
}
if (frequency <= nums.length / 2) {
throw new IllegalArgumentException(
"Majority element does not exist");
}
return candidate;
}
}
Complexity remains:
Time: O(n)
Space: O(1)
The array is traversed twice.
Edge Cases
Single Element
Input
[5]
Output
5
A single element is automatically the majority.
All Elements Are the Same
Input
[4,4,4,4]
Output
4
Majority Appears at the Beginning
Input
[3,3,3,1,2]
Output
3
Majority Appears at the End
Input
[1,2,4,4,4]
Output
4
Negative Numbers
Input
[-1,-1,-1,2,3]
Output
-1
Array with Two Values
Input
[7,7,2]
Output
7
Comparison of Approaches
| Approach | Time | Space | Modifies Input | Recommended |
|---|---|---|---|---|
| Brute Force | O(n²) | O(1) | No | No |
| HashMap | O(n) | O(n) | No | Good |
| Sorting | O(n log n) | Sorting-dependent | Yes | Acceptable |
| Boyer-Moore | O(n) | O(1) | No | Best |
Common Interview Mistakes
Mistake 1 — Returning the Most Recent Candidate Without Understanding the Guarantee
Boyer-Moore returns a valid majority only when a majority element is guaranteed or verified afterward.
Mistake 2 — Using >= n / 2
The majority condition is:
count > n / 2
not:
count >= n / 2
For example, in an array of size 4, a value appearing 2 times is not a majority.
Mistake 3 — Confusing Majority with Mode
The mode is the most frequent element.
A majority must appear more than half the time.
Example:
[1,1,2,2,3]
Both 1 and 2 are modes, but no majority exists.
Mistake 4 — Forgetting Sorting Modifies the Input
Arrays.sort(nums);
changes the original array.
Mention this trade-off during interviews.
Mistake 5 — Using a HashMap Without Discussing Space
The HashMap solution is linear time but requires up to:
O(n)
extra space.
Mistake 6 — Incorrect Candidate Reset
The candidate must be reset only when:
count == 0
Production Applications
The majority-element pattern appears in:
- Election result processing
- Distributed consensus analysis
- Most common event detection
- Feature flag adoption tracking
- Customer behavior analysis
- Log event classification
- Fraud signal aggregation
- Dominant category detection
- Monitoring alert analysis
- Telemetry processing
Real-World Example — Election Voting
Suppose votes are represented as:
[A, A, B, A, C, A, A]
Candidate A appears:
5 times out of 7
Since:
5 > 7 / 2
A has an absolute majority.
Boyer-Moore can identify the majority candidate using constant extra memory.
Real-World Example — Distributed Systems
Suppose several nodes report a configuration version:
[v3, v3, v2, v3, v1, v3, v3]
If one version appears on more than half the nodes, it may be treated as the dominant cluster state.
The same cancellation principle can identify the candidate efficiently.
However, real distributed consensus requires stronger correctness guarantees than simple majority counting.
Follow-Up Question 1 — What If Majority Is Not Guaranteed?
Use Boyer-Moore to identify a candidate.
Then count its frequency in a second pass.
Return the candidate only when:
frequency > n / 2
Follow-Up Question 2 — Find Elements Appearing More Than n/3 Times
This becomes LeetCode #229 — Majority Element II.
There can be at most two such elements.
Use an extended Boyer-Moore algorithm with:
- Two candidates
- Two counters
- Verification pass
Follow-Up Question 3 — Find Elements Appearing More Than n/k Times
There can be at most:
k - 1
such elements.
A generalized Boyer-Moore algorithm maintains up to k - 1 candidates.
Follow-Up Question 4 — What If the Input Is a Stream?
If the majority element is guaranteed, Boyer-Moore works well for streaming data because it requires only:
O(1)
memory.
If verification is required and the stream cannot be replayed, additional storage or an external counting system may be necessary.
Follow-Up Question 5 — Can Sorting Be Used?
Yes.
After sorting, return:
nums[nums.length / 2];
But sorting requires:
O(n log n)
time and modifies the array.
Follow-Up Question 6 — Can HashMap Be Better Than Boyer-Moore?
HashMap is easier to understand and can provide:
- Exact frequencies
- Support for no-majority scenarios
- Frequency reporting for every value
Boyer-Moore is better when:
- Only the majority candidate is needed
- Memory must remain constant
- Majority existence is guaranteed
Interview Explanation
A strong interview explanation could be:
The optimal solution is the Boyer-Moore Voting Algorithm. I maintain a candidate and a counter. When the counter becomes zero, I select the current element as the new candidate. Matching values increase the counter, while different values decrease it. Since the majority element appears more times than all other elements combined, it cannot be completely canceled and remains as the final candidate. This gives O(n) time and O(1) extra space.
Interview Tips
Interviewers commonly ask:
- What is the difference between majority and most frequent?
- Why does Boyer-Moore work?
- Why can there be only one majority element?
- Is a verification pass required?
- What happens if majority is not guaranteed?
- How would you solve the
n / 3version? - Why is sorting valid?
- What is the HashMap space complexity?
- Can the algorithm process streaming input?
- Explain the cancellation logic with a dry run.
Always explain the cancellation intuition before writing the code.
Unit Tests
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class MajorityElementTest {
private final MajorityElement solution =
new MajorityElement();
@Test
void shouldFindMajorityInSmallArray() {
int[] nums = {3, 2, 3};
assertEquals(
3,
solution.majorityElement(nums));
}
@Test
void shouldFindMajorityInLargerArray() {
int[] nums = {2, 2, 1, 1, 1, 2, 2};
assertEquals(
2,
solution.majorityElement(nums));
}
@Test
void shouldHandleSingleElement() {
int[] nums = {5};
assertEquals(
5,
solution.majorityElement(nums));
}
@Test
void shouldHandleNegativeValues() {
int[] nums = {-1, -1, -1, 2, 3};
assertEquals(
-1,
solution.majorityElement(nums));
}
@Test
void shouldHandleAllSameValues() {
int[] nums = {4, 4, 4, 4};
assertEquals(
4,
solution.majorityElement(nums));
}
}
Summary
The Majority Element problem demonstrates how a counting problem can be optimized from a frequency map to a constant-space voting algorithm.
The HashMap solution is intuitive and runs in linear time but requires additional memory.
Sorting provides a concise solution but costs O(n log n) time and modifies the array.
The Boyer-Moore Voting Algorithm is optimal because it uses the cancellation property of the majority element.
Optimal complexity:
Time: O(n)
Space: O(1)
Key Takeaways
- A majority element appears more than
n / 2times. - There can be only one majority element.
- Brute force requires O(n²) time.
- HashMap provides O(n) time and O(n) space.
- Sorting places the majority element at the middle index.
- Boyer-Moore uses candidate cancellation.
- The majority element survives all cancellations.
- The optimal algorithm runs in O(n) time.
- The optimal algorithm uses O(1) extra space.
- Verify the candidate when majority existence is not guaranteed.
- Understand the difference between majority and mode.
- Practice the
n / 3follow-up problem.