Majority Element (opens in a new tab) Easy
Problem
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
Input: nums = [2,2,1,1,1,2,2] Output: 2
Summary
To solve this problem, we can use a hash table to count the number of occurrences of each element in the input array. We can then return the element with the highest count.
Solution
In TypeScript
function majorityElement(nums: number[]): number {
const counts = new Map<number, number>();
let maxCount = 0;
let majority = 0;
for (const num of nums) {
counts.set(num, (counts.get(num) ?? 0) + 1);
if (counts.get(num) > maxCount) {
maxCount = counts.get(num);
majority = num;
}
}
return majority;
}
In Python
from typing import List
def majorityElement(nums: List[int]) -> int:
counts = {}
maxCount = 0
majority = 0
for num in nums:
counts[num] = counts.get(num, 0) + 1
if counts[num] > maxCount:
maxCount = counts[num]
majority = num
return majority
Step-by-step explanation
- We initialize an empty hash table counts, a variable maxCount to keep track of the maximum count of any element seen so far, and a variable majority to keep track of the element with the highest count seen so far.
const counts = new Map<number, number>();
- We iterate over the input array nums using a for...of loop.
for (const num of nums) {
// ...
}
- For each element num in nums, we check if num is already in counts. If it is, we increment its count by 1. If it is not, we add it to counts with an initial count of 1.
counts.set(num, (counts.get(num) ?? 0) + 1);
- We then check if the count of num in counts is greater than maxCount. If it is, we update maxCount to be the count of num, and update majority to be num.
if (counts.get(num) > maxCount) {
maxCount = counts.get(num);
majority = num;
}
- After iterating over all elements in nums, we return majority.
return majority;
Complexity Analysis
Time Complexity
The time complexity of this solution is O(n), where n is the length of the input array. The algorithm iterates over the input array once and performs constant time operations on each element, including hash table lookups and updates.
Space Complexity
The space complexity of this solution is O(n), where n is the length of the input array. The space required to store the hash table is proportional to the number of distinct elements in the input array, which is at most n in the worst case if all elements are distinct.
Variations
There are actually several different algorithms that can be used to solve this problem, each with its own time and space complexity. Here are a few variations:
Sorting
One simple approach is to sort the input array and return the element at index ⌊n/2⌋, where n is the length of the array. Since the majority element always appears more than ⌊n/2⌋ times, this element is guaranteed to be the majority element. The time complexity of this approach is O(n log n) due to the sorting step, and the space complexity is O(1) if we sort the input array in-place, or O(n) if we create a sorted copy of the input array.
In TypeScript
function majorityElement(nums: number[]): number {
nums.sort();
return nums[Math.floor(nums.length / 2)];
}
In Python
def majorityElement(nums: List[int]) -> int:
nums.sort()
return nums[len(nums) // 2]
Hash Table
As demonstrated in the solution above, we use a hash table to count the number of occurrences of each element in the input array. This approach has a time complexity of O(n), since we iterate over the input array once, and a space complexity of O(n), since we need to store the counts of each element in the hash table.
Boyer-Moore Voting Algorithm
The Boyer-Moore Voting Algorithm is a clever algorithm that can find the majority element in O(n) time and O(1) space. The basic idea is to keep track of a "candidate" element that may be the majority element, and a count of how many times it has been seen. We iterate over the input array, updating the candidate and count as follows:
- If the count is 0, set the current element as the candidate.
- If the current element is equal to the candidate, increment the count.
- If the current element is not equal to the candidate, decrement the count.
- After iterating over the array, the candidate element is the majority element.
This algorithm works because the majority element appears more than ⌊n/2⌋ times, so its count will never become negative, and it will always be the candidate element at the end of the iteration.
In TypeScript
function majorityElement(nums: number[]): number {
let candidate = 0;
let count = 0;
for (const num of nums) {
if (count === 0) {
candidate = num;
}
if (num === candidate) {
count++;
} else {
count--;
}
}
return candidate;
}
In Python
from typing import List
def majorityElement(nums: List[int]) -> int:
candidate = 0
count = 0
for num in nums:
if count == 0:
candidate = num
if num == candidate:
count += 1
else:
count -= 1
return candidate
Divide and Conquer
The Divide and Conquer approach involves recursively splitting the input array in half, finding the majority element in each half, and then merging the results. This approach has a time complexity of O(n log n) in the worst case, but it can be faster than the other approaches on certain inputs. The basic idea is as follows:
- If the array has length 1, return the element as the majority element.
- Recursively find the majority element in the left half of the array.
- Recursively find the majority element in the right half of the array.
- If the majority elements in the left and right halves are the same, return that element as the majority element.
- Otherwise, count the number of occurrences of each candidate element in the entire array, and return the element with the highest count as the majority element.
In TypeScript
function majorityElement(nums: number[]): number {
if (nums.length === 1) {
return nums[0];
}
const mid = Math.floor(nums.length / 2);
const left = majorityElement(nums.slice(0, mid));
const right = majorityElement(nums.slice(mid));
if (left === right) {
return left;
}
const leftCount = nums.filter((num) => num === left).length;
const rightCount = nums.filter((num) => num === right).length;
return leftCount > rightCount ? left : right;
}
In Python
from typing import List
def majorityElement(nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
mid = len(nums) // 2
left = majorityElement(nums[:mid])
right = majorityElement(nums[mid:])
if left == right:
return left
leftCount = len([num for num in nums if num == left])
rightCount = len([num for num in nums if num == right])
return left if leftCount > rightCount else right