Majority Element easy
Problem Statement
Given an array nums
of size n
, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋
times. You may assume that the majority element always exists in the array.
Example 1:
Input: nums = [3,2,3] Output: 3
Example 2:
Input: nums = [2,2,1,1,1,2,2] Output: 2
Steps
There are several ways to solve this problem. We'll explore two efficient approaches:
Approach 1: Hash Map (Unordered Map)
- Create a hash map: Use an
unordered_map
to store each element innums
as a key and its count as the value. - Iterate and count: Iterate through the array. For each element, increment its count in the hash map.
- Find the majority: After iterating, iterate through the hash map and find the element with a count greater than
n / 2
.
Approach 2: Boyer-Moore Voting Algorithm
This algorithm is remarkably efficient. It leverages the fact that the majority element appears more than half the time.
- Initialize: Start with a
candidate
element (initially the first element) and acount
(initialized to 1). - Iterate: Iterate through the array, starting from the second element.
- If the current element is the same as the
candidate
, incrementcount
. - If the current element is different from the
candidate
:- Decrement
count
. - If
count
becomes 0, replace thecandidate
with the current element and resetcount
to 1.
- Decrement
- If the current element is the same as the
- Return: After iterating, the
candidate
will be the majority element. (A final check isn't strictly necessary since the problem states the majority element always exists).
Explanation
Approach 1 (Hash Map): This approach is straightforward but uses extra space proportional to the number of unique elements in the array.
Approach 2 (Boyer-Moore): This is a linear time and constant space solution. The intuition is that when you encounter a different element, you cancel out a count of the candidate. If the candidate is truly the majority element, it will survive these cancellations.
Code (C++)
#include <iostream>
#include <unordered_map>
#include <vector>
class Solution {
public:
// Approach 1: Hash Map
int majorityElementHashMap(std::vector<int>& nums) {
std::unordered_map<int, int> counts;
for (int num : nums) {
counts[num]++;
}
int n = nums.size();
for (auto const& [key, val] : counts) {
if (val > n / 2) {
return key;
}
}
return -1; // Should not reach here based on problem constraints
}
//Approach 2: Boyer-Moore Voting Algorithm
int majorityElementBoyerMoore(std::vector<int>& nums) {
int candidate = nums[0];
int count = 1;
for (size_t i = 1; i < nums.size(); ++i) {
if (nums[i] == candidate) {
count++;
} else {
count--;
if (count == 0) {
candidate = nums[i];
count = 1;
}
}
}
return candidate;
}
};
int main() {
std::vector<int> nums1 = {3, 2, 3};
std::vector<int> nums2 = {2, 2, 1, 1, 1, 2, 2};
Solution sol;
std::cout << "Majority element (HashMap): " << sol.majorityElementHashMap(nums1) << std::endl; // Output: 3
std::cout << "Majority element (HashMap): " << sol.majorityElementHashMap(nums2) << std::endl; // Output: 2
std::cout << "Majority element (Boyer-Moore): " << sol.majorityElementBoyerMoore(nums1) << std::endl; // Output: 3
std::cout << "Majority element (Boyer-Moore): " << sol.majorityElementBoyerMoore(nums2) << std::endl; // Output: 2
return 0;
}
Complexity
Approach 1 (Hash Map):
- Time Complexity: O(n), where n is the length of the input array. We iterate through the array once to count elements and then iterate through the hash map (which in the worst case could be of size n).
- Space Complexity: O(k), where k is the number of unique elements in the array. This can be at most O(n) in the worst case.
Approach 2 (Boyer-Moore Voting Algorithm):
- Time Complexity: O(n) – A single pass through the array.
- Space Complexity: O(1) – Constant extra space is used. No additional data structures that scale with input size are needed.