第一眼看到這個題目,想到的是使用Map來統計出現頻次,然後遍歷找出頻次大於n/2
的元素。
class Solution {
public int majorityElement(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for(Integer item: nums){
if(null != map.get(item)){
map.put(item, map.get(item) + 1);
}else
map.put(item,1);
}
for(Integer freq: map.keySet()){
if(map.get(freq) > (nums.length / 2))
return freq;
}
return -1;
}
}
但是顯而易見的是:沒有用上n/2
這個設定。
其實這個看似簡單的問題有一個特殊的解法,就是我們要說的***Boyer–Moore majority vote algorithm*** :摩爾投票法
知乎上有老哥給出了非常形象的解釋:
核心是對拼消耗:類似我們玩的即時戰略遊戲:魔獸爭霸,三國羣英傳等。假設地圖上有一家(稱作紅色軍)擁有所有軍隊中一半以上的小兵,在直接對拼下不虛任何對手(不同隊伍小兵1v1地同歸於盡),其他隊伍像藍色、綠色、紫色等,有可能會互相消耗,但是最後留在地圖上的一定是同一隊人數最多的紅色。
如何理解摩爾投票算法? - 知乎用戶的回答 - 知乎
https://www.zhihu.com/question/49973163/answer/617122734
具體實現:
class Solution{
public int majorityElement(int[] nums){
int res = 0;
int count = 0;
for (int num : nums) {
if (count == 0) {
res = num;
}
count += (num == res) ? 1 : -1;
}
return res;
}
有興趣的話還可以再看一下下面這個
wiki上的僞代碼:
The algorithm maintains in its local variables a sequence element and a counter, with the counter initially zero.
It then processes the elements of the sequence, one at a time. When processing an element x, if the counter is zero, the algorithm stores x as its remembered sequence element and sets the counter to one.
Otherwise, it compares x to the stored element and either increments the counter (if they are equal) or decrements the counter (otherwise).
At the end of this process, if the sequence has a majority, it will be the element stored by the algorithm. This can be expressed in pseudocode as the following steps:
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
Even when the input sequence has no majority, the algorithm will report one of the sequence elements as its result.
However, it is possible to perform a second pass over the same input sequence in order to count the number of times the reported element occurs and determine whether it is actually a majority. This second pass is needed, as it is not possible for a sublinear-space algorithm to determine whether there exists a majority element in a single pass through the input.