Majority Element-I
LeetCode ↗ Java source ↗ Edit this article ↗
Jump to code:
Problem
You are given an integer array nums of length n. The majority element is a value that appears strictly more than n / 2 times (integer division). Return it. The LeetCode version guarantees that a majority element always exists; the version here returns -1 when there is none, which costs one extra verification pass and makes the solution usable on arbitrary input.
Note the word “strictly”: in [1, 1, 2, 2] the value 1 appears exactly n / 2 = 2 times, which is not a majority. There can be at most one majority element, because two values each appearing more than half the time would need more than n elements.
Constraints: 0 ≤ n ≤ 5 × 10^4, values fit in a 32-bit signed integer.
Example 1
nums = [3, 2, 3]
answer = 3 // 3 appears 2 times, 2 > 3/2 = 1
Example 2
nums = [2, 2, 1, 1, 1, 2, 2]
answer = 2 // 2 appears 4 times, 4 > 7/2 = 3
Example 3
nums = [1, 2, 3]
answer = -1 // nothing appears more than once
Approach 1: Brute force
Intuition. For every element, count how many times its value occurs in the whole array and compare with n / 2. The first element that passes is the answer.
Algorithm.
- For every index
i: - Count indices
jwithnums[j] == nums[i]. - If
count > n / 2, returnnums[i]. - Return
-1.
static int bruteForce(int[] nums) {
int n = nums.length;
for (int i = 0; i < n; i++) {
int count = 0;
for (int j = 0; j < n; j++) {
if (nums[j] == nums[i]) count++;
}
if (count > n / 2) return nums[i];
}
return -1;
}
Complexity. Time O(n^2): each element triggers a full scan. Space O(1).
Approach 2: Better, a frequency map
Intuition. Count all values in one pass with a hash map instead of re-scanning. As soon as some value’s count exceeds n / 2 we can stop; it cannot be beaten. If the loop finishes, no value made it.
Algorithm.
- Create an empty map
freq. - For every
x: incrementfreq[x]; if the new count is> n / 2, returnx. - Return
-1.
static int better(int[] nums) {
Map<Integer, Integer> freq = new HashMap<>();
for (int x : nums) {
int c = freq.merge(x, 1, Integer::sum);
if (c > nums.length / 2) return x;
}
return -1;
}
Complexity. Time O(n) on average. Space O(n): in the worst case (no majority) the map holds every distinct value.
A second “better” option worth knowing: sort and look at the middle. If a majority exists, it occupies more than half of the sorted array, so it must cover the middle index n / 2. That is O(n log n) time and, if sorting in place is allowed, O(1) extra space. You still need a counting pass to confirm the candidate when a majority is not guaranteed.
Approach 3: Optimal, Boyer-Moore voting
Intuition. Imagine every occurrence of the majority element as a vote for it and every other element as a vote against. Because the majority has more than half the elements, even if every other element cancels one majority vote, at least one majority vote survives. Boyer-Moore turns this into an algorithm with two variables: a candidate and a votes counter.
Walk the array. If votes is 0, adopt the current element as the candidate with one vote. Otherwise, if the element equals the candidate, add a vote; if it differs, remove one. Whenever votes drops to 0, the segment just finished contained the candidate exactly as many times as all other values combined, so throwing that segment away removes equally many majority and non-majority elements. The majority element is still the majority of what remains. By induction, the candidate at the end is the only value that can be the majority.
That last word is important: if no majority exists, the algorithm still ends with some candidate. So we count its occurrences in a second pass and return -1 if it falls short. When the problem guarantees a majority, this pass can be skipped.
Algorithm.
- Set
candidate = 0,votes = 0. - For every
x:- if
votes == 0:candidate = x,votes = 1; - else if
x == candidate:votes++; - else:
votes--.
- if
- Count how many times
candidateoccurs. Return it if the count is> n / 2, else-1.
static int optimal(int[] nums) {
int candidate = 0, votes = 0;
for (int x : nums) {
if (votes == 0) {
candidate = x;
votes = 1;
} else if (x == candidate) {
votes++;
} else {
votes--;
}
}
int count = 0;
for (int x : nums) if (x == candidate) count++;
return count > nums.length / 2 ? candidate : -1;
}
Dry run on nums = [2, 2, 1, 1, 1, 2, 2]:
| x | votes before | action | candidate | votes after |
|---|---|---|---|---|
| 2 | 0 | adopt 2 | 2 | 1 |
| 2 | 1 | same, +1 | 2 | 2 |
| 1 | 2 | differs, -1 | 2 | 1 |
| 1 | 1 | differs, -1 | 2 | 0 |
| 1 | 0 | adopt 1 | 1 | 1 |
| 2 | 1 | differs, -1 | 1 | 0 |
| 2 | 0 | adopt 2 | 2 | 1 |
The candidate is 2; the verification pass counts four occurrences, 4 > 3, so return 2. Notice that the candidate was briefly 1 in the middle; the algorithm does not need the candidate to be right at every step, only at the end.
Complexity. Time O(n): two passes. Space O(1): two integers.
Why does cancellation preserve the majority? Suppose the majority value m occurs c > n / 2 times. Each time votes returns to 0 after a segment of length L, that segment contained exactly L / 2 copies of the then-candidate and L / 2 other elements. Whether or not the candidate was m, at most L / 2 copies of m were in the segment, so after discarding it m still has more than half of the remaining elements. The final segment (where votes ends positive) is therefore dominated by m, and its candidate is m.
Edge cases and pitfalls
- Empty array. All three methods return
-1. In the voting version the candidate stays0and the count0is not greater than0. - Exactly half (
[1, 1, 2, 2]) is not a majority. Use>withn / 2, not>=. For oddn,n / 2rounds down, so[3, 2, 3]needs a count of at least2. - Single element (
[1]) is a majority:1 > 0. - Negative values work everywhere; the only subtlety is that
-1doubles as the “none” marker in this version of the problem. If-1can be a legitimate answer in your setting, return anOptionalor a boolean flag instead. - Skipping the verification pass is only safe when a majority is guaranteed. Without it,
[1, 2, 3]would return3. - Overflow is not a concern: counts are at most
n. n / 2withnums.length / 2: integer division is exactly what the definition uses, so noMath.flooris needed.
Related problems
- Majority Element-II asks for elements appearing more than
n / 3times; the voting idea generalises to two candidates. - Find the number that appears once, and other numbers twice. is another counting problem solved in
O(1)space by a cancellation argument, there with XOR. - Sort an array of 0’s 1’s and 2’s is the previous problem on the sheet; both replace sorting by a structural observation.