The blog for Design Patterns, Linux, HA and Myself!
This document presents the solution to the problem 169. Majority Element - Leetcode.
This problem requires finding the element, from an unsorted array, appearing more than length(array) / 2 times.
There are multiple ways to find the majority element with different size and space complexity based algorithms.
Here’s one approach in which I’ve sorted the array and then counted the presence of the each element.
func majorityElementUsingSort(nums []int) int {
sort.Ints(nums) // requires importing the sort package.
current := nums[0]
currentCount := 0
majorityElement := nums[0]
majorityElementCount := 0
for _, num := range nums {
if current == num {
currentCount++
} else {
if majorityElementCount < currentCount {
majorityElement = current
majorityElementCount = currentCount
}
current = num
currentCount = 1
}
}
return majorityElement
}
Since the array is sorted, I can choose to just create 4 state variable for counting:
current - The current element in the loopcurrentCount - The count of the current elementmajorityElement - The element having the highest count until nowmajorityElementUsingSort- The count of the majorityElementHow has sorting helped here?
n, we can be sure that n will never be found again.n, we can compare the count of n with the count of majorityElement found so far.n is higher than the count of majorityElement, n becomes the majorityElement.Time Complexity: O(n * log(n)) due to sorting
Space Complexity: O(n)
AFAIK, there exists atleast 2 solutions that solve this problem in linear time complexity.
The second approach looked interesting and I choose to implement it.
Approach:
result, initiailized to 0.1 - 31: i
currentBitPresenceCountnums: num
currentBitPresenceCount if the current bit position i is set on numcurrentBitPresenceCount is greater than length(nums)
i on resultI’ve skipped the 32nd bit position because the input is signed integer array. This is not a correct approach as it does not handle the negative numbers. We will look into the correct approach after discussing the shortcomings in the current approach.
func majorityElementUsingBitWiseOperation(nums []int) int {
result := 0
for i := 0; i < 31; i++ {
currentBitPresenceCount := 0
for _, num := range nums {
if num&(1<<i) == (1 << i) {
currentBitPresenceCount++
}
}
if currentBitPresenceCount > len(nums)/2 {
result |= 1 << i
}
currentBitPresenceCount = 0
}
return result
}
Why does it not work with negative numbers?
3 becomes 00000000000000000000000000000011.-3 becomes 11111111111111111111111111111101.In two’s complement representation:
000000111111110011111101This representation breaks the logic.
Here’s the solution that handles the negative numbers too:
func majorityElementUsingBitWiseOperation(nums []int) int {
negativeCount := 0
result := 0
for i := 0; i < 31; i++ {
currentBitPresenceCount := 0
for _, num := range nums {
if num < 0 {
if i == 30 {
negativeCount++
}
num = -num
}
if num&(1<<i) == (1 << i) {
currentBitPresenceCount++
}
}
if currentBitPresenceCount > len(nums)/2 {
result |= 1 << i
}
currentBitPresenceCount = 0
}
if negativeCount > len(nums)/2 {
return -result
}
return result
}
Changes:
negativeCount counter.Please do provide some comments if you find the explanation a bit lacking.