1. 题目描述Description
Link: https://leetcode.com/problems/majority-element/description/
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋
times.
You may assume that the array is non-empty and the majority element always exists in the array.
给定一个size为n的数组,找出众数。其中众数出现了大于 ⌊ n/2 ⌋次。
2. 思路Thoughts
这题比较有意思的是,有一个优于hash map的算法 - 由Robert S. Boyer和J Strother Moore发表的MJRTY - A Fast Majority Vote Algorithm。
这个算法有一个限制就是这个众数必须要出现大于 ⌊ n/2 ⌋次。
由可以看到 wikipedia 伪代码可以写成:
- Initialize an element m and a counter i with i = 0
- For each element x of the input sequence:
- If i = 0, then assign m = x and i = 1
- else if m = x, then assign i = i + 1
- else assign i = i − 1
- Return m
怎么去思考这个问题呢?思路是这样的:
假设我有AAAAABBCD,很明显A是我们要找的目标。假设A出现了$x$次,非A的字母出现了$y$次,那么我们肯定有 $x > $ ⌊ n/2 ⌋ 而且$x>y$必须成立。
这也就意为着,如果我们删去其中任何两个不一样的字母$c_1$和$c_2$,而且这两个字母符合$c_1 e c_2$,那么:
a) 如果这两个字母包含A,例如删去A和C,那么$x = x - 1$, $y = y-1$, $x>y$依然成立因为$x-1>y-1 if x>y$。
b) 如果这两个字母都不包含A,例如删去B和D,那么$x$不变,$y=y-2$,$x>y$依然成立因为$x>y-2 if x > y$
所以如果删去任何两个不一样的字母,并不影响最后的结果。删完了不一样的,留下的一定会是那个目标众数。
3. 代码Code
class Solution { public int majorityElement(int[] nums) { int count = 1, current = nums[0]; for(int i = 1; i < nums.length; i++) { if(count == 0) { count++; current = nums[i]; } else if(current==nums[i]) count++; else count--; } return current; } }