1. 程式人生 > 其它 >使用摩爾投票法解決多數問題

使用摩爾投票法解決多數問題

1、什麼是摩爾投票法

博耶-摩爾多數投票演算法(英語:Boyer–Moore majority vote algorithm),中文常作多數投票演算法摩爾投票演算法等,是一種用來尋找一組元素中佔多數元素的常數空間級時間複雜度演算法。

這一演算法應用的問題原型是在集合中尋找可能存在的多數元素,這一元素在輸入的序列重複出現並佔到了序列元素的一半以上;在第一遍遍歷之後應該再進行一個遍歷以統計第一次演算法遍歷的結果出現次數,確定其是否為眾數;如果一個序列中沒有佔到多數的元素,那麼第一次的結果就可能是無效的隨機元素。對於資料流而言,則不太可能在亞線性空間複雜度的情況下中就尋找到出現頻率最高的元素;而對於序列,其元素的重複次數也有可能很低。

上面的描述來自維基百科。過程可以分為兩個階段:

(1)投票階段:即投票人之間票數進行抵消。

(2)計數階段:計算對抗結果中最後剩下的那個候選人票數是否有效。

2、例題

在LeetCode上,有下面幾題

(1)面試題 17.10. 主要元素

(2)169. 多數元素

第(1)道屬於不一定存在多數元素的情況,第(2)道屬於存在多數元素的情況。對於一定存在多數元素的情況,我們可以不用進行計數階段。

所以我們直接看第(1)題,因為第一題包含了第(2)題的解法。

題目

陣列中佔比超過一半的元素稱之為主要元素。給你一個 整數 陣列,找出其中的主要元素。若沒有,返回 -1 。請設計時間複雜度為 O(N) 、空間複雜度為 O(1) 的解決方案。

示例 1:

輸入:[1,2,5,9,5,9,5,5,5]
輸出:5

示例 2:

輸入:[3,2]
輸出:-1

示例 3:

輸入:[2,2,1,1,1,2,2]
輸出:2

分析

以示例2為例,[2, 2, 1, 1, 1, 2, 2]

這是存在多數元素的情況,對於不存在多數元素的情況,比如[1, 2, 3]這樣的個數為奇數的序列,如果按照上面的方法,最後求的major值為3,這是一個錯誤的答案。

所以對於不一定存在多數元素的情況下, 我們在求得major後,需要再遍歷一次,統計這個major在序列中出現的次數是否大於n / 2,即驗證票數是否有效。

編碼

class Solution {
    public int majorityElement(int[] nums) {
        int major = 0, count = 0;
        for (int i = 0; i < nums.length; i++) {
            if (count == 0) {
                major = nums[i];
            }
            if (major == nums[i]) {
                count++;
            } else {
                count--;
            }
        }

        count = 0;
        for (int num : nums) {
            if (num == major) {
                count++;
            }
        }

        return (count <= nums.length / 2) ? -1 : major;
    }
}