169. Majority Element - Explanation
Description
Given an array nums of size n, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times in the array. You may assume that the majority element always exists in the array.
Example 1:
Input: nums = [5,5,1,1,1,5,5]
Output: 5Example 2:
Input: nums = [2,2,2]
Output: 2Constraints:
1 <= nums.length <= 50,000-1,000,000,000 <= nums[i] <= 1,000,000,000
Follow-up: Could you solve the problem in linear time and in O(1) space?
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Hash Maps - Counting element frequencies efficiently for O(n) time solutions
- Sorting - Understanding that after sorting, the majority element occupies the middle position
- Boyer-Moore Voting Algorithm - The candidate elimination technique that finds majority elements in O(1) space
- Bit Manipulation - Constructing numbers bit by bit by counting set bits across all elements (for the bit manipulation approach)
1. Brute Force
Intuition
The majority element appears more than n/2 times. For each element, we can count how many times it appears in the array. If the count exceeds n/2, we've found our answer. This straightforward approach checks every element against every other element.
Algorithm
- For each element
numin the array:- Count how many times
numappears in the entire array. - If the count exceeds
n / 2, returnnum.
- Count how many times
- A majority element is guaranteed to exist, so we will always find one.
Time & Space Complexity
- Time complexity:
- Space complexity:
2. Hash Map
Intuition
We can avoid repeated counting by using a hash map to store the frequency of each element as we iterate through the array. We track the element with the maximum count seen so far. Once any element's count exceeds n/2, it must be the majority element.
Algorithm
- Create a hash map to store element frequencies.
- Initialize
resandmaxCountto track the current best candidate. - For each element
num:- Increment its count in the hash map.
- If its count exceeds
maxCount, updateres = numandmaxCount = count[num].
- Return
res.
Time & Space Complexity
- Time complexity:
- Space complexity:
3. Sorting
Intuition
If we sort the array, the majority element must occupy the middle position. Since it appears more than n/2 times, no matter where the majority element's block starts, it will always include the index n/2. This gives us a simple one-liner solution after sorting.
Algorithm
- Sort the array.
- Return the element at index
n / 2.
Time & Space Complexity
- Time complexity:
- Space complexity: or depending on the sorting algorithm.
4. Bit Manipulation
Intuition
We can construct the majority element bit by bit. For each bit position, we count how many numbers have that bit set. If more than n/2 numbers have the bit set, then the majority element must also have that bit set. We build the result by combining all the majority bits.
Algorithm
- Create an array to count set bits at each of the 32 positions.
- For each number, add
1tobit[i]if thei-th bit is set. - For each bit position, if
bit[i] > n / 2, set that bit in the result. - Handle the sign bit (bit 31) specially for negative numbers.
- Return the constructed result.
class Solution:
def majorityElement(self, nums: List[int]) -> int:
n = len(nums)
bit = [0] * 32
for num in nums:
for i in range(32):
bit[i] += ((num >> i) & 1)
res = 0
for i in range(32):
if bit[i] > (n // 2):
if i == 31:
res -= (1 << i)
else:
res |= (1 << i)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
represents the number of bits as the given numbers are integers.
5. Boyer-Moore Voting Algorithm
Intuition
The Boyer-Moore algorithm works by maintaining a candidate and a count. When we see the candidate, we increment the count; otherwise, we decrement it. When the count reaches 0, we pick a new candidate. Since the majority element appears more than half the time, it will survive this elimination process and remain as the final candidate.
Algorithm
- Initialize
resas the candidate andcount = 0. - For each element
num:- If
count == 0, setres = num. - If
num == res, incrementcount; otherwise decrementcount.
- If
- Return
resas the majority element.
Time & Space Complexity
- Time complexity:
- Space complexity:
6. Randomization
Intuition
Since the majority element appears more than n/2 times, any random pick has greater than 50% chance of selecting it. We repeatedly pick a random element and check if it's the majority. On average, we need only about 2 picks to find the answer, making this surprisingly efficient in practice.
Algorithm
- Randomly select an element from the array.
- Count how many times it appears.
- If the count exceeds
n / 2, return it. - Otherwise, repeat from step 1.
Time & Space Complexity
- Time complexity:
- Space complexity:
The probability of randomly choosing the majority element is greater than , so the expected number of iterations in the outer while loop is constant.
Common Pitfalls
Using >= Instead of > for the Majority Check
The majority element must appear more than n/2 times, not n/2 or more. Using count >= n/2 instead of count > n/2 can return incorrect results for arrays like [1, 2, 2] where 2 appears exactly n/2 times but is not a strict majority.
Forgetting Integer Division Semantics
In languages like Python 3, / performs floating-point division while // performs integer division. Using n / 2 instead of n // 2 can lead to type errors or incorrect comparisons. Similarly, in JavaScript, Math.floor(n / 2) is needed for proper integer division.
Sign in to join the discussion