Jargon: Majority Element is an element of an array that occurs more than half the number of times in the array. Also, [x] means smallest integer greater than x.
Easy Problem: Assume that an integer array A[1..n] has a majority element and elements other than majority element are distinct. How to find majority element. What's the space and time complexity of the algorithm ?
Answer: Time Complexity = n/2(comparisons), Space Complexity = O(1)
Solution: show
We will use pigeonhole principle to make our clever observations. There can be a maximum of [n/2]-1 elements that are distinct, remaining [n/2] element have to be same (as majority element exists in the array). We can consider that the [n/2]-1 distinct elements to be laid out and the space between two laid out elements to be a basket of infinite size. So we will have [n/2] baskets. If we try to distribute [n/2] majority element to these baskets, then in only one permutation will each basket get one element. Otherwise, some baskets would get more than one element and some baskets would remain empty.
Using this observation, we can claim that to find majority element we need to check adjacent elements for equality or two hop neighbor (adjacent to neighbor) for equality. That requires two comparison per element and the algorithm would look like this:
for i <- 1 to n-2
if A[i] == A[i+1] or A[i] == A[i+2]
return A[i]
A quick observation tells that this algorithm's for loop would stop when i=[3n/4]+1 even in worst case and the number of comparisons done will be ~ 3n/2.
Now, we can make another clever observation that is, if we do not find two adjacent elements to be equal after complete scanning of array, then first element has to be majority element by pigeonhole principle.
for i <- 1 to n-1
if A[i] == A[i+1]
return A[i]
return A[1]
In Worst case this algorithms stops at i=n+1 and the number of comparisons done is = n-1. Even though this looks better than the first solution but it could be worse in practice. On a highly pipelined architecture with branch prediction, first one is much better than the second one, even though it does more comparisons per loop. So testing for large array sizes with random shuffling of elements will give clear insight into which algorithm is faster.
Now an extremely clever solution which is based on observation that if we pair array elements and strike out a pair if its both the elements are distinct or else return the pair element as majority element. If all pair are striked out then what ever element is left has to be majority element.
i = 1
while i <= n
if A[i] == A[i+1]: return A[i]
i+= 2
return A[n]
Worst case analysis tells that algorithms would stop when i=n-1 and the number of comparisons done is ~ n/2. This is indeed the best in worst case that we can do. Cheers
Hard Problem: Assume that an integer array A[1..n] has a majority element and elements other than majority element need NOT be distinct. How to find majority element. What's the space and time complexity of the algorithm?
Answer:
Time Complexity=n(comparison), Space Complexity=O(1).
Solution: show
This algorithm uses an observation that if we consider our array to be list of voters and array value is the candidate to whom they are voting, then majority element is the winning candidate. Additionally, if all other candidates are merged to form one candidate then still it will fail to defeat the majority element candidate (hence the name majority element).
So we can think of it this way. Assuming a negative vote decrease the count of majority element then still the count of majority element would be atleast 1. This algorithm implements the above idea.
element = A[1]
votes = 1
for i <- 2 to n:
if A[i] == element
votes += 1
else if votes > 0
votes -= 1
else:
element = A[i]
votes = 1
return element
This algorithm takes n-1 steps in all cases. In worst case this algorithm performs n comparisons.
Note: Comparisons in this context means comparison between the actual array elements. Comparisons such as votes > 0 don't count as they are integer variable comparison.
Tip: Algorithms must be designed while keeping input into account. Additionally, if an algorithm performs many complex calculations then it doesn't necessarily is worse due to pipeline execution of instructions and branch predictions, pre-fetching and other advances in hardware.
2 comments:
Super solution i like it :)
beautiful soln....
Post a Comment